'(SOLVED) How to update parent model in laravel?
[SOLVED] /*** The parent-children relationship works fine. But there was a code i wrote several weeks ago that prevent me to update the progress value. ***/
I have a project that has similar functionality to trello (kanban) There are 3 models which are projects, TaskList (columns), Tasks (cards).
a project has many columns
a column has many tasks
a task has many
subtasks (the subtask refer to the model itself)
each model has a column named progress. This column must be updated when the children are updated. The progress is calculated by averaging the progress of all cards.
Models : Project.php
class Project extends Model
{
use HasFactory;
protected $table = 'projects';
public $timestamps = true;
protected $fillable = [
'id','title', 'description', 'actual_start', 'actual_end',
'start', 'end','progress'
];
public function updateProgress(){
$sum=0;
if(count($this->columns)){
for ($i = 0; $i < count($this->columns); $i++) {
$list = $this->columns[$i];
if($list->progress==null){
$list->progress=0;
}
$sum+=$list->progress;
}
$progress=$sum/count($this->columns);
$this->progress=round($progress);
$this->save();
}
return $this->progress;
}
public function scopeExclude($query, $value = [])
{
return $query->select(array_diff($this->fillable, (array) $value));
}
public function lists(){
return $this->hasMany(TaskList::class,'projects_id');
}
TaskList.php
class TaskList extends Model
{
protected $table = 'lists';
protected $fillable = [ 'title', 'position', 'projects_id', 'start', 'end', 'actual_start', 'actual_end','progress' ];
public static function boot() {
parent::boot();
static::saved(function($list){
$list->project->updateProgress();
});
}
public function updateProgress(){
$tes=[];
if(count($this->cards)){
$sum=0;
for ($i = 0; $i < count($this->cards); $i++) {
$task = $this->cards[$i];
if($task->progress==null){
$task->progress=0;
}
$sum+=$task->progress;
$tes[]=['id'=>$task->id,'progress'=>$task->progress,$task->cards];
}
$progress=$sum/count($this->cards);
$this->progress=round($progress);
$this->save();
}
return ['id'=>$this->id,'progress'=>$this->progress,'cards'=>$this->cards];
}
public function cards(){
return $this->hasMany(Task::class,'lists_id');
}
}
Task.php
class Task extends Model
{
use HasFactory;
protected $table = 'tasks';
public $timestamps = true;
protected $fillable = [
'id','users_id', 'title', 'description', 'complete', 'end', 'start',
'actual_start', 'actual_end', 'start_label', 'end_label',
'progress', 'is_subtask', 'lists_id','parent_task_id'
];
protected $casts = [
'progress' => 'double',
];
public static function boot() {
parent::boot();
static::saving(function($task){
if(!empty($task->start) && !empty($task->end)){
$start = Carbon::parse($task->start);
$end = Carbon::parse($task->end);
$days= $start->diffInDays($end);
$task->days=$days+1;
}
if(!empty($task->actual_start) && !empty($task->actual_end)){
$actual_start = Carbon::parse($task->actual_start);
$actual_end = Carbon::parse($task->actual_end);
$work_days= $actual_start->diffInDays($actual_end);
$task->work_days=$work_days+1;
}
// This part was the problem
if($task->parentTask){
if($task->actual_end){
$task->progress=100;
}else{
$task->progress=0;
}
}else{
if($task->actual_end){
$task->progress=100;
}else{
$task->progress=0;
}
}
if($task->parentTask){
if($task->actual_end){
$task->progress=100;
}else{
$task->progress=0;
}
}else{
if($task->actual_end){
$task->progress=100;
}else{
$task->progress=0;
}
}
//------------------------
if($task->progress==100){
$task->complete=true;
}
});
static::saved(function($task){
//is a subtask
if($task->parentTask){
// dd('subtask',$task->id,$task->complete,$task->progress,$task->parentTask,$task->list);
$task->parentTask->updateProgress();
}else{
// dd('parent task',$task->id,$task->complete,$task->progress,$task->parentTask,$task->list);
$task->list->updateProgress();
// dd('list ',$task->list->updateProgress());
}
});
static::deleting(function($task) {
foreach ($task->members as $i => $member) {
$member->delete();
}
foreach ($task->cards as $k => $subtask) {
$subtask->delete();
}
$task->tags()->detach();
$task->task_members()->detach();
});
}
public function updateProgress(){
if(count($this->cards)){
$valuePerSubtask=100/count($this->cards);
$completeSubtaskCounter=0;
for ($i = 0; $i < count($this->cards); $i++) {
$subtask = $this->cards[$i];
if($subtask->complete){
$completeSubtaskCounter++;
}
}
$progress=$completeSubtaskCounter*$valuePerSubtask;
$this->progress=$progress;
$this->save();
return [$this->progress,$progress];
}
}
public function scopeExclude($query, $value = [])
{
return $query->select(array_diff($this->fillable, (array) $value));
}
public function parentTask(){
return $this->belongsTo(Task::class,'parent_task_id');
}
public function list(){
return $this->belongsTo(TaskList::class,'lists_id');
}
}
I can't update the parent task from the children. As you can see in Task.php model, I have a updateProgress() that return [$this->progress, $progress]; after i call $this->save(). I already have $this->progress=$progress before i save it. But $this->progress still show the same result.
[![the first item is $this->progress, the second one is $progress][1]][1]
[1]: https://i.stack.imgur.com/RS2mq.png
i tried override touch() and place updateProgress() inside it. But still doesn't show the expected result.
Any advice for a better approach? Am I missing something?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
