(已解决)如何更新LARLAVEL中的父模型?

2022-08-07 00:00:00 php laravel laravel-8

[已解决] /* 亲子关系运作良好。但是,几周前我编写了一个代码,它阻止我更新进度值。 */

我有一个与Trello(看板)功能类似的项目 有项目、任务列表(列)、任务(卡片)3种模型。

  • 一个项目有许多列

  • 一列有多个任务

  • 一个任务有多个

    子任务(子任务指的是模型本身)

每个模型都有一个名为Progress的列。在更新子对象时,必须更新此列。进度是通过对所有卡片的进度求平均值来计算的。

型号: 项目.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');
    }
 
}


我无法从子任务更新父任务。正如您在Task.php模型中看到的那样,在我调用$this->save()之后,我有一个return [$this->progress, $progress];upateProgress()。在我保存它之前,我已经有$this->progress=$progress。但$this->progress仍显示相同的结果。

[![第一项是$this->progress,第二项是$progress][1]][1] [1]:https://i.stack.imgur.com/RS2mq.png

我尝试覆盖touch()并将updateProgress()放入其中。但仍未显示预期结果。

有什么更好的方法建议吗? 我错过了什么吗?


解决方案

解决方案也可以是:

创建任务的观察者。

php artisan make:observer TaskObserver

然后在观察者中。

class UserObserver
{
    //SOME METHODS

   public function updated(Task $task)
   {
       /* Important, this will be done with all tasks on update in the tree
          like Task->task->task etc... unless you put some extra logic. But 
          this is the general idea
       */

       #search if parent
       if ($task->parent_task_id !== null) {
           //run progress
            $task->parentTask->updateProgress()
       }
   }

}

相关文章