通过引用Laravel事件侦听器传递数组

时间:2019-05-28 02:28:20

标签: php laravel laravel-5 laravel-5.8

我在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. 
    }
}

4 个答案:

答案 0 :(得分:0)

根据array的文档,内容如下:

  

数组分配始终涉及值复制。使用引用运算符按引用复制数组。

因此将您的构造方法改为:

// prepend the argument with the reference operator &
public function __construct(array &$data) 

答案 1 :(得分:0)

我感谢所有答复,对问题的反馈和建议,以寻求更好的解决方法。

现在,我尝试使用Laravel Pipeline,而不是使用侦听器,这是一种通过不同管道传递数据并过滤数据的好方法。本文对于了解它https://jeffochoa.me/understanding-laravel-pipelines

很有帮助。

这是代码的最终版本,以及我如何使用Laravel Pipeline:

节点: 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);
    }
}

答案 2 :(得分:0)

只需在事件的构造函数中使用参考符号:

/**
 * @param array $data
 * 
 */
public function __construct(array &$data)
{
    $this->data = &$data;
                  ^
}

尽管这可以为问题提供准确的答案,但我不建议针对此特定用例使用观察者模式。

此外,您不需要访问器-只需公开data属性并在侦听器中使用$event->data

答案 3 :(得分:0)

被触发的初始事件是通过引用传递的(因为它是一个对象)。侦听器执行后可以访问该对象中修改后的 $data 属性。

import platform
if platform.system == "Windows":
    os.environ['SDL_VIDEODRIVER'] = 'windib'

无需在事件构造函数或 getter 中通过引用手动传递任何内容。