如何在接收事件的多个 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
在您的侦听器中可用,希望对您有所帮助。
使用流明 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
在您的侦听器中可用,希望对您有所帮助。