通过引用 Laravel 事件侦听器传递数组
Pass array by reference to Laravel Event Listener
我在 Laravel 应用程序中有一个数组,我想在 Laravel 侦听器中对其进行修改。 PHP 默认情况下按值传递数组,但是 Laravel 事件及其侦听器的工作方式我无法修改原始变量。有没有比我下面做的更好的方法?
触发事件的模型。
型号:Event.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.
}
}
事件:PageNodeToArrayAfter.php
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;
}
}
听众:FlashMessagesListner.php
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.
}
}
根据 array 的文档,内容如下:
Array assignment always involves value copying. Use the reference operator to copy an array by reference.
因此,请将您的构造函数改为:
// prepend the argument with the reference operator &
public function __construct(array &$data)
我感谢所有回复、对问题的反馈以及寻找更好方法的建议。
现在我没有使用监听器,而是尝试了 Laravel 管道,这是通过不同管道传递数据并在我的例子中过滤数据的好方法。这篇文章对理解它很有帮助https://jeffochoa.me/understanding-laravel-pipelines
这是我的代码的最终版本以及我如何使用 Laravel 管道:
节点:Page.php
<?php declare(strict_types=1);
namespace Vendor\Package\Nodes;
class Page extends ReactPage
{
public function toArray() : array
{
$data = parent::toArray();
$pipes = [
AppendFlashMessage::class,
RemoveEmptyLayoutNode::class
];
// Filter data through the pipelines.
$data = app(Pipeline::class)
->send($data)
->through($pipes)
->via('filter')
->then(function($data) {
return $data;
});
return $data;
}
}
管道:AppendFlashMessage.php
<?php declare(strict_types=1);
namespace Vendor\Package\Pipeline;
use Closure;
class AppendFlashMessage
{
public function filter(array $data, Closure $next) : array
{
// step 1: pull the errors from session.
$errors = [
'type' => 'error',
'message' => 'Invalid User Name'
];
$data['messages'] = $errors;
return $next($data);
}
}
只需在事件的构造函数中使用引用符号:
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = &$data;
^
}
虽然这提供了问题的准确答案,但我不建议对这个特定用例使用观察者模式。
此外,您不需要访问器 - 只需创建 data
属性 public 并在您的侦听器中使用 $event->data
。
触发的初始事件通过引用传递(因为它是一个对象)。侦听器执行后可以访问该对象中修改的$data 属性。
event($e = new PageNodeToArrayAfter($data));
$data = $e->getData();
无需在事件构造函数或getter中通过引用手动传递任何内容。
我在 Laravel 应用程序中有一个数组,我想在 Laravel 侦听器中对其进行修改。 PHP 默认情况下按值传递数组,但是 Laravel 事件及其侦听器的工作方式我无法修改原始变量。有没有比我下面做的更好的方法?
触发事件的模型。
型号:Event.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.
}
}
事件:PageNodeToArrayAfter.php
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;
}
}
听众:FlashMessagesListner.php
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.
}
}
根据 array 的文档,内容如下:
Array assignment always involves value copying. Use the reference operator to copy an array by reference.
因此,请将您的构造函数改为:
// prepend the argument with the reference operator &
public function __construct(array &$data)
我感谢所有回复、对问题的反馈以及寻找更好方法的建议。
现在我没有使用监听器,而是尝试了 Laravel 管道,这是通过不同管道传递数据并在我的例子中过滤数据的好方法。这篇文章对理解它很有帮助https://jeffochoa.me/understanding-laravel-pipelines
这是我的代码的最终版本以及我如何使用 Laravel 管道:
节点:Page.php
<?php declare(strict_types=1);
namespace Vendor\Package\Nodes;
class Page extends ReactPage
{
public function toArray() : array
{
$data = parent::toArray();
$pipes = [
AppendFlashMessage::class,
RemoveEmptyLayoutNode::class
];
// Filter data through the pipelines.
$data = app(Pipeline::class)
->send($data)
->through($pipes)
->via('filter')
->then(function($data) {
return $data;
});
return $data;
}
}
管道:AppendFlashMessage.php
<?php declare(strict_types=1);
namespace Vendor\Package\Pipeline;
use Closure;
class AppendFlashMessage
{
public function filter(array $data, Closure $next) : array
{
// step 1: pull the errors from session.
$errors = [
'type' => 'error',
'message' => 'Invalid User Name'
];
$data['messages'] = $errors;
return $next($data);
}
}
只需在事件的构造函数中使用引用符号:
/**
* @param array $data
*
*/
public function __construct(array &$data)
{
$this->data = &$data;
^
}
虽然这提供了问题的准确答案,但我不建议对这个特定用例使用观察者模式。
此外,您不需要访问器 - 只需创建 data
属性 public 并在您的侦听器中使用 $event->data
。
触发的初始事件通过引用传递(因为它是一个对象)。侦听器执行后可以访问该对象中修改的$data 属性。
event($e = new PageNodeToArrayAfter($data));
$data = $e->getData();
无需在事件构造函数或getter中通过引用手动传递任何内容。