首页 > 解决方案 > Laravel 广播事件的构造函数调用的类型再次提示模型关系

问题描述

几天来我一直无法弄清楚为什么会发生我在底部描述的以下行为。
以下代码的基本思想是更新任务,并且

任务控制器

在这里,我更新了一些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; 
    } 


}

问题

The event itself is broadcasted and recieved succesfully, the one thing that i dont get is why the Task model relations, that are loaded already in the controller, are loaded again in the event, therefore, duplicating the database queries.
When I open up the Laravel Telescope tool, I can see that the neccesary queries are executed in the controller but once the Task model is passed to the event, the event job runs some of the queries, that have been executed in the controller, again. In the end, if I remove and add some employees from the task, up to ~40 queries have been run, even though it should take around 17 queries.
If I log the Task model, that is passed to the event, in constructor before this line $this->task = $task;, I can see that the relationships are already loaded, but when $this->task = $task; is executed, laravel loads the relationships again.
Shouldnt the relationships be already loaded?If not, how could I reduce the amount of queries? Might this be a Laravel Telescope glitch and those queries are no actually executed?

标签: phplaravel

解决方案


Laravel serializes the Task model instance when it is pushed to the queue. When the broadcast happens, the Task is re-retrieved from the database again.


推荐阅读