Laravel广播事件的构造函数调用的类型再次提示模型关系

时间:2019-02-25 12:28:27

标签: php laravel

我几天来一直无法弄清为什么发生在下面我将要描述的以下行为。
以下代码的基本思想是更新任务,然后

  • 向已分配任务的员工广播EmployeeTaskAttached事件
  • 广播EmployeeTaskDetached那些已被删除任务的员工
  • TaskEmployeesChanged用于那些未受影响但需要使用新添加/删除的员工更新其任务员工列表的员工
  • Task模型应在加载关系的情况下进行广播

任务控制器

在这里,我更新了一些Task字段,从sync()返回的数据中获取了已附加/分离的员工的ID,并相应地广播了事件。 请注意,我加载了显示任务所需的视图所需的任务关系。
 $task->load('project','status','parent_task','tags') ;

 public function update (Request $request, Task $task)
{    
  $task->name = $request->task['name'];
  $task->date_due = $request->task['date_due'];
  $task->type()->associate($request->task['task_type_id']);  
  $task->status()->associate($request->task['status_id']);
  $task->load('project','status','parent_task','tags') ;

  if($request->has('task.employees') )
  {
    $originalEmployees = $task->employees->pluck('id'); 
    $changedEmployees = $task->employees()->sync($request->input('task.employees',[]));
    $detachedEmployees = $changedEmployees['detached'];
    $attachedEmployees = $changedEmployees['attached'];
    //$employeesToUpdate contains the original task employee id's that have not been detached or attached
    $employeesToUpdate = $originalEmployees->diff(array_merge($detachedEmployees,$attachedEmployees ));
    if( $attachedEmployees || $detachedEmployees)
    { 
      //broadcasted only if there is a change in employees
      broadcast(new TaskEmployeesChanged($task,$employeesToUpdate));
    }
    if($attachedEmployees)
    { 
      broadcast(new EmployeeTaskAttached($task,collect($attachedEmployees)));
    }
    if($detachedEmployees)
    {
     broadcast(new EmployeeTaskDetached($task,collect($detachedEmployees)));
    } 

  }  
  $task->save();
}

广播事件

这是事件之一,但其他事件发生相同的行为。

namespace App\Events\Tasks;  
use Illuminate\Broadcasting\Channel;  
use Illuminate\Queue\SerializesModels;  
use Illuminate\Broadcasting\PrivateChannel;  
use Illuminate\Broadcasting\PresenceChannel;  
use Illuminate\Foundation\Events\Dispatchable;  
use Illuminate\Broadcasting\InteractsWithSockets;  
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;  
use App\Models\Task;  
use App\Interfaces\UserInterface;  
class EmployeeTaskAttached implements ShouldBroadcast  
{  
    use Dispatchable, InteractsWithSockets, SerializesModels;  

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public $task,$employee_id ;
    public function __construct(Task $task,$employee_id   )
    {
      $this->task = $task;
      $this->employee_id = $employee_id; 
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    { 
      $task_list_channels = $this->employee_id->map(function ($id){
        $channel = new PrivateChannel('task_list_'.$id);
       return $channel;
      }) 
      ->all();

      return $task_list_channels; 
    } 


}

问题

成功地广播并接收了事件本身,我没有得到的一件事是为什么已经在控制器中加载的Task模型关系在事件中再次加载,因此,复制了数据库查询。
当我打开Laravel望远镜工具时,可以看到在控制器中执行了必要的查询,但是将Task模型传递给事件后,事件作业将运行一些查询,这些查询已在控制器,再次。最后,如果我从任务中删除并添加了一些员工,尽管可能需要大约17个查询,但已经运行了约40个查询。
如果在行Task之前的构造函数中记录传递给事件的$this->task = $task;模型,则可以看到关系已经加载,但是当执行$this->task = $task;时,laravel重新加载关系。
关系是否应该已经加载?如果没有,如何减少查询量? 可能这是Laravel望远镜故障,实际上没有执行这些查询吗?

1 个答案:

答案 0 :(得分:0)

Laravel在将Task模型实例推送到队列时对其进行序列化。广播发生时,Task再次从数据库中检索。