我目前正在使用 Laravel 的队列事件侦听器处理 Eloquent 模型的saving
事件。在我的事件类上,我设置了一个包含我的模型的公共属性,然后我可以$event
通过$event->myModel
.
我的侦听器上的handle()
方法将旧值与新值进行比较,因此我Illuminate\Queue\SerializesModels
在事件类中删除了。这很好用,我现在可以比较新值中的旧值。
问题在于测试。我正在做一个测试,检查我在侦听器方法中得到的新旧值handle()
是否不同。但是,$event->myModel->getOriginal()
现在返回一个空数组。这仅在测试时发生。
这是一个错误吗?
我尝试public $originalModelProps
在我的事件类上设置 a 但是,当调用我的侦听器上的 handle() 方法时它返回空。
我没有使用或在我的代码中Illuminate\Queue\SerializesModels
命名的任何特征/类/接口。SerializesModels
事件/模型/MyModel/MyModelSavedEvent.php
<?php
namespace App\Events\Models\MyModel;
use App\Models\MyModel;
use Illuminate\Queue\SerializesModels;
class MyModelSavedEvent
{
/**
*
* @var \App\Models\MyModel
*/
public $myModel;
public $originalAccessLevelProps;
/**
* Create a new event instance.
*
* @param \App\Models\MyModel
*
* @return void
*/
public function __construct(MyModel $myModel)
{
$this->myModel = $myModel;
$this->originalAccessLevelProps = $this->myModel->getOriginal('level');
}
}
Listeners/Models/MyModel/MyModelSavedEventListener.php
<?php
namespace App\Listeners\Models\MyModel;
use Log;
use App\Models\MyModel;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Events\Models\MyModel\MyModelSavedEvent;
class MyModelSavedEventListener implements ShouldQueue
{
/**
* The queue connection that should handle the job.
*
* @var string
*/
public $connection = 'sqs';
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries = 3;
/**
* The number of seconds the job can run before timing out.
*
* @var int
*/
public $timeout = 60;
public function __construct()
{
// ..
}
/**
* This job should only be queued if the level of myModel
* has been updated.
*
* @param \App\Events\Models\MyModel\MyModelSavedEvent $event
*
* @return bool
*/
public function shouldQueue(MyModelSavedEvent $event)
{
$prevLevel = $event->myModel->getOriginal('level');
$currLevel = $event->myModel->level;
return $prevLevel !== $currLevel;
}
public function handle(MyModelSavedEvent $event): void
{
$prevLevel = $event->myModel->getOriginal('level');
$currLevel = $event->myModel->level;
Log::info([
'Running handle!',
$event->myModel->getOriginal(), // This returns an empty array
$event->originalAccessLevelProps, // This is null
$event->myModel->id, // This returns a string
$prevLevel, // This returns null
$currLevel // This contains the latest value
]);
// ..
}
}
测试/app/Listeners/Models/MyModel/MyModelSavedEventListener.php
<?php
public function testSample()
{
Queue::fake();
$myModel = MyModel::where(...)->first();
Queue::assertNothingPushed();
// This will trigger the event
$myModel->level = 'new level';
$myModel->save();
Queue::assertPushedOn('sqs', MyModelSavedEventListener::class);
}
我期待类似于它在测试之外的工作方式,我将能够比较旧值和新值。
编辑:
事件是通过 MyModel 的$dispatchesEvents
属性触发的:
/**
* The event map for the model.
*
* @var array
*/
protected $dispatchesEvents = [
'saved' => \App\Events\Models\MyModel\MyModelSavedEvent::class,
];
更新:发现我的模型确实没有被序列化。只是在侦听器的方法getOriginal()
中调用时仍然返回一个空数组handle()