如何在接收事件的多个 Laravel/Lumen 侦听器中保存模型状态?

How can I preserve model state across multiple Laravel/Lumen listeners that receive an event?

使用流明 5.5,PHP7.3

我的目标是在保持代码整洁的同时扩展模型的现有功能。使用 Event/Listener 模式是有道理的,但我遇到了一些设计问题,我需要在侦听器中访问模型的原始状态。该状态似乎不可访问。

它是如何开始的:模型上的这个方法(为 public 查看而消毒)通过将 null 分配给某些属性来“重置”它。没问题。

    public function reset()
    {
        $this->association_id = null;
        $this->associated_at = null;
        $this->save();
    }

进展如何: 添加了事件分派,以便我可以向侦听器添加新功能。

    public function reset()
    {
        $this->association_id = null;
        $this->associated_at = null;
        $this->save();

        event(new ResetEvent($this));
    }

活动

class ResetEvent
{
    public $myModel;

    public function __construct($myModel)
    {
        $this->myModel = $myModel;
    }
}

听众

class ResetListener
{
    public function handle(ResetEvent $event)
    {
        $association_id = $event->myModel->association_id;
        // OR...
        $association_id = $event->myModel->getOriginal('association_id');

        // Do new functionality...
    }
}

挑战

侦听器需要访问模型中的 association_id 值。不幸的是,在从模型的重置方法调用 save() 方法后,这不再可用。我确实尝试在侦听器的模型上使用 getOriginal() 方法,但那里的值也为 null。感觉应该有用。

请注意,此实现使用同步事件;不涉及外部异步排队系统。

选项

一种选择是将意图和名称从 ResetEvent 更改为 ResetRequestEvent 并使用一个侦听器对模型执行属性修改,另一个执行新功能添加。如果模型通过引用传递给侦听器,这可能会或可能不会导致竞争条件。

另一种选择可能是一种我还没有学会的方法,可以在模型传递给事件时保留它的状态。 Java 风格的数据传输对象浮现在脑海中,但这听起来像是在躲避框架提供的奢侈品。

寻找进一步选择的想法。

您可以将其他参数传递给您的事件。例如:

 public function reset()
 {
    $lastAssociation = $this->association_id;
    $this->association_id = null;
    $this->associated_at = null;
    $this->save();

    event(new ResetEvent($this, $lastAssociation));
 }

然后您的活动将是:

class ResetEvent
{
    public $myModel;
    public $lastAssociationId;

    public function __construct($myModel, $lastAssociationId)
    {
        $this->myModel = $myModel;
        $this->lastAssociationId = $lastAssociationId;
    }
}

最后一个关联将作为 $event->lastAssociationId 在您的侦听器中可用,希望对您有所帮助。