如何将侦听器代码从闭包移到方法并在ZF2中将参数传递给它?

问题描述 投票:1回答:2

我有一个Module类,其onBootstrap(...)中有多个“内联”事件监听器:

...
class Module
{
    public function onBootstrap(MvcEvent $mvcEvent)
    {
        ...
        $foo = ...;
        ...
        $halPlugin = $viewHelperManager->get('Hal');
        $halPlugin->getEventManager()->attach('bar', function ($event) {
            ...
        });
        ...
        $halPlugin->getEventManager()->attach('baz', function ($event) use ($foo)
        {
            ...
        });
        ...
    }
    ...
}

现在,为了保持/使Module#onBootstrap(...)变细,我想将监听器从闭包移到单独的方法。这对onBar事件监听器来说没问题。但它对onBaz不起作用,需要额外的输入:

...
class Module
{
    public function onBootstrap(MvcEvent $mvcEvent)
    {
        ...
        $halPlugin->getEventManager()->attach('bar', [$this, 'onBar']);
        ...
    }
    ...
    public function onBar()
    {
        ...
    }
    public function onBaz() // <-- How to pass $foo to the method?
    {
        // Some stuff, that needs $foo...
        ...
    }
}

在原始变体中,此输入通过use指令传递到闭包中。但是现在该怎么做?

如何将带有Module#onBootstrap(...)语句的闭包中的事件监听器(附加在use中)的逻辑移动到单独的方法并将参数传递给它?

php event-handling zend-framework2 closures
2个回答
1
投票

你可以做的是将foo作为模块类的属性移动,然后使用$this->foo访问它

class Module
{
    private $foo;

    public function onBootstrap(MvcEvent $mvcEvent)
    {
        $this->foo = ...;
        $halPlugin->getEventManager()->attach('baz', [$this, 'onBaz']);
        ...
    }
    ...
    public function onBaz()
    {
        $this->foo
        // Some stuff, that needs $foo...
        ...
    }
}

您还可以使模块中的函数返回Closure,您可以使用函数发送$foo

class Module
{
    public function onBootstrap(MvcEvent $mvcEvent)
    {
        $foo = ...;
        $halPlugin->getEventManager()->attach('baz', $this->onBaz($foo));
        ...
    }
    ...
    public function onBaz($foo)
    {
        return function ($event) use ($foo) {
            $this->foo
            // Some stuff, that needs $foo...
            ...
        }
    }
}

2
投票

将您的方法移动到侦听器类。

听众只需要是Callable,这意味着在你的类中声明__invoke()方法并将你拥有的所有代码放在当前的onBaz()方法中

<?php

namespace SomeModule\Listener;

class BazListener
{

    protected $foo;

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

    public function __invoke()
    {
         // code from onBaz() method using $this->foo
    }
}

你会注意到$ foo现在是一个需要构造函数注入的依赖项。为了实现依赖,为你的监听器类编写工厂,在工厂中获取$foo并将其注入其中。

<?php

namespace SomeModule\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class BazListenerFactory implements FactoryInterface
{
     public function createService(ServiceLocatorInterface $services)
     {
          //fetch foo from wherever ..
          $foo = ;
          return new \SomeModule\Listener\BazListener($foo);
     }
}

现在将监听器工厂添加到服务管理器,以便您可以在onBootstrap中访问它

return array(
     'service_manager' => (
         'factories' => (
             // ..
             'SomeModule\Listener\BazListener' => 'SomeModule\Factory\BazListenerFactory',
             // ..
         ),
    ),
);

最后从onBootstrap中的服务管理器获取您的侦听器作为服务,并将其附加到您的事件管理器

public function onBootstrap(MvcEvent $mvcEvent)
{
    $bazListener = $mvcEvent->getApplication()
                            ->getServiceManager()
                            ->get('SomeModule\Listener\BazListener');
    $halPlugin->getEventManager()->attach('bar', $bazListener);
    ...
}

这是一些额外的工作,但它更好地区分了问题,你现在有一个独立的监听器,你可以重用,而不是依赖Module类的复制/粘贴方法。

© www.soinside.com 2019 - 2024. All rights reserved.