Php 拉威尔广播活动';s构造函数调用';s型再次暗示了模型关系
我已经好几天没有弄清楚为什么会发生下面我在下面描述的行为。Php 拉威尔广播活动';s构造函数调用';s型再次暗示了模型关系,php,laravel,Php,Laravel,我已经好几天没有弄清楚为什么会发生下面我在下面描述的行为。 下面代码的基本思想是更新任务,以及 向已分配任务的员工广播EmployeeTaskAttached事件 为已从任务中删除的员工广播EmployeeTaskDistached TaskEmployeesChanged适用于未受影响但需要使用新添加/删除的员工更新其任务员工列表的员工 任务模型广播时应加载关系 任务控制器 在这里,我更新了一些任务字段,从sync()返回的数据和相应的广播事件中获取附加/分离员工的id。 请注意,我加载了
下面代码的基本思想是更新任务,以及
- 向已分配任务的员工广播
事件EmployeeTaskAttached
- 为已从任务中删除的员工广播
EmployeeTaskDistached
适用于未受影响但需要使用新添加/删除的员工更新其任务员工列表的员工TaskEmployeesChanged
模型广播时应加载关系任务
任务
字段,从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;
}
}
问题
事件本身被成功地广播和接收,我不明白的一件事是,为什么已经在控制器中加载的任务
模型关系会在事件中再次加载,从而复制数据库查询。
当我打开Laravel望远镜工具时,我可以看到必要的查询在控制器中执行,但一旦任务
模型传递给事件,事件作业就会再次运行一些在控制器中执行的查询。最后,如果我从任务中删除并添加一些员工,则最多可以运行40个查询,尽管它应该需要大约17个查询。
如果我将传递给事件的任务
模型记录在此行$this->Task=$Task之前的构造函数中代码>,我可以看到已经加载了关系,但是当$this->task=$task代码>执行后,laravel再次加载关系。
是否应该已经加载关系?如果没有,我如何减少查询量?
这可能是拉威尔望远镜的一个小故障,而这些查询并没有实际执行 Laravel将任务
模型实例推送到队列时序列化。当广播发生时,任务
将再次从数据库中检索 Laravel将任务
模型实例推送到队列时序列化。当广播发生时,任务
将再次从数据库中检索 也许这与序列化模型的特性有关。您的任务模型将被序列化并放入队列中。也许当它被从广播队列中拉出来时,关系会被重新加载。@DelenaMalan你是对的,这篇博文对此解释得很好,它为什么这样设计是有道理的。谢谢,也许你可以把你的评论作为一个答案发表。也许这和序列化模型的特性有关。您的任务模型将被序列化并放入队列中。也许当它被从广播队列中拉出来时,关系会被重新加载。@DelenaMalan你是对的,这篇博文对此解释得很好,它为什么这样设计是有道理的。谢谢,你可以把你的评论作为一个答案。