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;
}
}
问题
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?
解决方案
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.
推荐阅读
- android - 使用 vue.js 和 android 的移动应用程序的区别
- php - 当我使用 docker multi-stage build 构建生产应用程序时,如何删除 composer dev 依赖项?
- reactjs - React:我应该使用路由还是有条件地渲染一系列视图?
- python - 我在第 17 行有一个错误,在 pointsPlus points += 1*mult TypeError: unsupported operand type(s) for +=: 'Event' and 'int'
- sql - Need partition by three field and ranking
- python - 重新分区 dask 数据帧以减少滚动期间的改组
- javascript - jQuery:选择具有特定 HTML 标记的特定 DOM
- c# - C# - 从列表字典创建新列表
- reactjs - 有没有办法在反应组件上描述道具,以便用户可以更好地自动完成?
- laravel - nuxt nginx 设置中的单个 Laravel 端点