(已解决)如何在 laravel 中更新父模型?
(SOLVED) How to update parent model in laravel?
[已解决]
/***
亲子关系很好。但是几周前我写了一段代码,阻止我更新进度值。
***/
我有一个与 trello(看板)功能相似的项目
有 3 个模型,分别是项目,TaskList(列),Tasks(卡片)。
一个项目有很多列
一个栏目有很多任务
一个任务有多个
子任务(子任务是指模型本身)
每个模型都有一个名为进度的列。更新子项时必须更新此列。进度以所有卡牌的进度平均计算。
型号:
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');
}
}
我无法更新子项的父任务。正如您在 Task.php 模型中看到的那样,在我调用 $this->save()
之后,我有一个 return [$this->progress, $progress];
的 updateProgress()。在保存之前我已经有 $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()
}
}
}
[已解决] /*** 亲子关系很好。但是几周前我写了一段代码,阻止我更新进度值。 ***/
我有一个与 trello(看板)功能相似的项目 有 3 个模型,分别是项目,TaskList(列),Tasks(卡片)。
一个项目有很多列
一个栏目有很多任务
一个任务有多个
子任务(子任务是指模型本身)
每个模型都有一个名为进度的列。更新子项时必须更新此列。进度以所有卡牌的进度平均计算。
型号: 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');
}
}
我无法更新子项的父任务。正如您在 Task.php 模型中看到的那样,在我调用 $this->save()
之后,我有一个 return [$this->progress, $progress];
的 updateProgress()。在保存之前我已经有 $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()
}
}
}