Как переместить код слушателя из замыкания в метод и передать ему аргументы в 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 оператор в отдельный метод и передать ему аргументы?

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...
...
}
}
}
1

Другие решения

Переместите ваш метод в класс слушателя.

Слушатель просто должен быть 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.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector