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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将侦听器代码从闭包移到方法并在ZF2中将参数传递给它?相关的知识,希望对你有一定的参考价值。

我有一个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中)的逻辑移动到单独的方法并将参数传递给它?

答案

你可以做的是将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...
            ...
        }
    }
}
另一答案

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

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

<?php

namespace SomeModuleListener;

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 SomeModuleFactory;

use ZendServiceManagerFactoryInterface;
use ZendServiceManagerServiceLocatorInterface;

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

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

return array(
     'service_manager' => (
         'factories' => (
             // ..
             'SomeModuleListenerBazListener' => 'SomeModuleFactoryBazListenerFactory',
             // ..
         ),
    ),
);

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

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

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

以上是关于如何将侦听器代码从闭包移到方法并在ZF2中将参数传递给它?的主要内容,如果未能解决你的问题,请参考以下文章

Ext Js 如何将参数传递给服务器代码

如何在 Delphi 2010 中将参数传递给 flash 电影?

如何将相同的事件侦听器分配给 Vue.js 中动态创建的按钮并将对象的值作为参数传递给它?

如何从类定义中将参数传递给元类?

从后面的代码将参数传递给 URL

如何通过原始指针将闭包作为参数传递给 C 函数?