Php 通过引用将数组传递给Laravel事件侦听器
我想在Laravel listener中修改Laravel应用程序中的一个数组。PHP默认情况下按值传递数组,但是,按照Laravel事件及其侦听器的工作方式,我无法修改原始变量。有没有比我在下面做的更好的方法 从中触发事件的模型 模型:Event.phpPhp 通过引用将数组传递给Laravel事件侦听器,php,laravel,laravel-5,laravel-5.8,Php,Laravel,Laravel 5,Laravel 5.8,我想在Laravel listener中修改Laravel应用程序中的一个数组。PHP默认情况下按值传递数组,但是,按照Laravel事件及其侦听器的工作方式,我无法修改原始变量。有没有比我在下面做的更好的方法 从中触发事件的模型 模型:Event.php namespace Vendor\Package\Models use Vendor\Package\Events\PageNodeArrayAfter; use Event; class Page { public functio
namespace Vendor\Package\Models
use Vendor\Package\Events\PageNodeArrayAfter;
use Event;
class Page
{
public function toArray()
{
$data = [];
// do something with the data.
Event::fire(new PageNodeToArrayAfter($data))
// The data should be modified by a listener when I use it here.
}
}
namespace Vendor\Package\Events;
class PageNodeToArrayAfter
{
/**
* Props to be sent to the view
* @var array $data
*/
protected $data = [];
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
}
namespace Vendor\Package\Listeners;
class FlashMessagesListner
{
protected $data = [];
public function handle(PageNodeToArrayAfter $event)
{
$this->data = $event->getData();
// The problem here is the $data is no logner a reference here.
}
}
事件:PageNodeToArrayAfter.php
namespace Vendor\Package\Models
use Vendor\Package\Events\PageNodeArrayAfter;
use Event;
class Page
{
public function toArray()
{
$data = [];
// do something with the data.
Event::fire(new PageNodeToArrayAfter($data))
// The data should be modified by a listener when I use it here.
}
}
namespace Vendor\Package\Events;
class PageNodeToArrayAfter
{
/**
* Props to be sent to the view
* @var array $data
*/
protected $data = [];
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
}
namespace Vendor\Package\Listeners;
class FlashMessagesListner
{
protected $data = [];
public function handle(PageNodeToArrayAfter $event)
{
$this->data = $event->getData();
// The problem here is the $data is no logner a reference here.
}
}
监听器:FlashMessagesListner.php
namespace Vendor\Package\Models
use Vendor\Package\Events\PageNodeArrayAfter;
use Event;
class Page
{
public function toArray()
{
$data = [];
// do something with the data.
Event::fire(new PageNodeToArrayAfter($data))
// The data should be modified by a listener when I use it here.
}
}
namespace Vendor\Package\Events;
class PageNodeToArrayAfter
{
/**
* Props to be sent to the view
* @var array $data
*/
protected $data = [];
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
}
namespace Vendor\Package\Listeners;
class FlashMessagesListner
{
protected $data = [];
public function handle(PageNodeToArrayAfter $event)
{
$this->data = $event->getData();
// The problem here is the $data is no logner a reference here.
}
}
根据该项目的文档,它是这样说的: 数组赋值总是涉及值复制。使用引用运算符按引用复制数组 因此,将构造函数改为:
// prepend the argument with the reference operator &
public function __construct(array &$data)
我感谢所有的回复、对问题的反馈以及寻找更好方法的建议 现在,我不再使用监听器,而是尝试了Laravel管道,这是一种通过不同管道传递数据并对其进行过滤的好方法。这篇文章对理解它很有帮助 以下是我的代码的最终版本,以及我如何使用Laravel管道: 节点:Page.php
namespace Vendor\Package\Models
use Vendor\Package\Events\PageNodeArrayAfter;
use Event;
class Page
{
public function toArray()
{
$data = [];
// do something with the data.
Event::fire(new PageNodeToArrayAfter($data))
// The data should be modified by a listener when I use it here.
}
}
namespace Vendor\Package\Events;
class PageNodeToArrayAfter
{
/**
* Props to be sent to the view
* @var array $data
*/
protected $data = [];
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
}
namespace Vendor\Package\Listeners;
class FlashMessagesListner
{
protected $data = [];
public function handle(PageNodeToArrayAfter $event)
{
$this->data = $event->getData();
// The problem here is the $data is no logner a reference here.
}
}
只需在事件的构造函数中使用引用符号:
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = &$data;
^
}
虽然这为问题提供了一个准确的答案,但我不建议在这个特定用例中使用观察者模式
此外,您不需要访问器—只需将数据
属性设置为公共,并在侦听器中使用$event->data
。触发的初始事件通过引用传递(因为它是一个对象)。在侦听器执行之后,可以访问该对象中已修改的$data属性
event($e = new PageNodeToArrayAfter($data));
$data = $e->getData();
无需在事件构造函数或getter中通过引用手动传递任何内容。这并不能回答问题。如何在侦听器中修改引用的变量?我刚刚更新了我的问题,并包含了&操作符,这本来是应该存在的。我现在只是使用setter和getter来修改变量,现在我可能不需要通过引用传递它。它回答了您声明在PHP中默认数组是通过引用传递的部分,而不是通过引用传递的部分。对我来说,首先使用监听器并从监听器内部修改外部变量是没有意义的,因为当你触发一个事件时,这个过程是异步的,即使监听器还没有完成它的工作,事件后的下一行也会被执行。是的,这就是我现在的想法。我可能不需要通过引用将变量传递给侦听器,因此也不需要我之前的注释。您的用例是什么?你为什么要做到这一点?您的主线程(执行事件的线程)将继续运行,即使您的侦听器可能尚未完成。我正在将一些XML节点转换为数组,在此过程中,我希望通过独立的侦听器附加一些自定义数据,如验证消息。我明白了。您需要自定义XML数据,那么为什么要使用侦听器呢?事件/侦听器用于向应用程序的其他部分(或外部API)通知某些内容,但在您的情况下,您希望对您将一直接触的相同数据进行操作。我理解您希望解耦逻辑,以避免用大量代码重新填充函数。因此,您可以将该逻辑提取到一个函数、一个trait或另一个将返回更新的XML文件的类中。我同意@HCK的观点,即观察者模式在这里是一种错误的方法,因为您的转换可能在侦听器完成其工作之前完成。事件和侦听器用于解耦进程。如果只需要将一些验证消息闪存到会话中,我看不出需要如何通过引用传递数组。如果侦听器的逻辑对于应用程序另一部分的处理至关重要,那么无论如何,侦听器是错误的选择。只有当触发流程不关心事件是否被任何其他流程使用时,才应该使用事件侦听器(就业务流程而言,是流程,而不是线程)。即,在用户注册后发送欢迎邮件(此过程完全可选)。