我有一个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 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类的复制/粘贴方法。