Как получить ссылку на диспетчер служб внутри метода инициализации модуля (ZF2)?

Мне нужно, чтобы некоторый код был выполнен до того, как любой MvcEvent::EVENT_BOOTSTRAP слушатель будет выполнен. Очевидно, что Module::onBootstrap не вариант. Я заканчиваю следующим кодом:

class Module
{

    function init(\Zend\ModuleManager\ModuleManager $moduleManager)
    {
        $moduleManager->getEventManager()->attach(
                MvcEvent::EVENT_BOOTSTRAP, array(ClassX, 'StaticMethodOfClassX'), 20000);
    }

}

Я не хочу жестко кодировать ссылку array(ClassX, 'StaticMethodOfClassX'), но получу ее от сервис-менеджера. Моя проблема в том, что я не знаю, как получить ссылку на диспетчер служб внутри метода инициализации модуля. Любая помощь? или это сейчас невозможно в ZF2? Любой вариант этой схемы или мнения тоже будет оценен;)

ИЗМЕНИТЬ:

Я уточню: «Очевидно, что Module::onBootstrap не вариант», потому что это может быть не так уж и тривиально;)

Методы Module::onBootstrap модулей выполняются, когда инициируется событие MvcEvent::EVENT_BOOTSTRAP, но привязка метода Module::onBootstrap каждого модуля к этому событию зависит от порядка загрузки модулей. Из-за того, что порядок, в котором будет выполняться конкретный метод Module::onBootstrap, зависит от того, какие другие модули существуют и как другие модули влияют на порядок, в котором этот конкретный модуль будет загружен. Кроме того, любой обработчик, прикрепленный к событию MvcEvent::EVENT_BOOTSTRAP с приоритетом больше 1, будет выполняться перед любым методом модуля Module::onBootstrap, например обработчиком ViewManager::onBootstrap. Итак, чтобы достичь того, что я хочу

Мне нужно, чтобы некоторый код был выполнен до того, как любой MvcEvent::EVENT_BOOTSTRAP слушатель будет выполнен

модули obBootstrap методы не вариант.


person Community    schedule 22.10.2013    source источник
comment
Почему вы не можете использовать onBootstrap?   -  person Tim Fountain    schedule 23.10.2013
comment
@TimFountain Спасибо за вопрос, Тим. Я редактирую свой вопрос, чтобы объяснить, почему нет. Спасибо еще раз.   -  person    schedule 23.10.2013


Ответы (5)


Это очень старый пост, но, поскольку ответ не был принят, и мне недавно нужно было добиться того же, я решил поделиться своим решением.

Причина, по которой мне нужно было получить доступ к ServiceManager до запуска события Bootstrap, заключалась в том, что я мог манипулировать объединенной конфигурацией со значениями, полученными из базы данных.

Проблема:

Пример из документации Zend показывает, как управлять объединенная конфигурация, но в это конкретное время диспетчер служб пуст, что делает невозможным извлечение таких вещей, как адаптеры базы данных и т. д.

Решение:

В классе вашего модуля реализуйте интерфейс InitProviderInterface и добавьте соответствующий метод.

public function init(ModuleManagerInterface $moduleManager)
{
    $eventManager = $moduleManager->getEventManager();
    $eventManager->attach(ModuleEvent::EVENT_LOAD_MODULES_POST, [$this, 'onLoadModulesPost']);
}

Событие EVENT_LOAD_MODULES_POST будет вызвано после события EVENT_MERGE_CONFIG, но до того, как будет инициировано событие EVENT_BOOTSTRAP. Также в это конкретное время ServiceManager будет содержать все фабрики, вызываемые классы, к которым вы хотите получить доступ.

Ваш метод обратного вызова может выглядеть примерно так.

public function onLoadModulesPost(ModuleEvent $event)
{
    /* @var $serviceManager \Zend\ServiceManager\ServiceManager */
    $serviceManager = $event->getParam('ServiceManager');
    $configListener = $event->getConfigListener();
    $configuration = $configListener->getMergedConfig(false);

    $someService = $serviceManager->get('Your/Custom/Service');
    $information = $someService->fetchSomeInformation();
    $configuration = array_merge($configuration, $information);

    $configListener->setMergedConfig($configuration);
    $event->setConfigListener($configListener);
    $serviceManager->setAllowOverride(true);
    $serviceManager->setService('Config', $configuration);
    $serviceManager->setAllowOverride(false);
}
person adamdyson    schedule 21.12.2015
comment
Привет, Адамдисон, я действительно изо всех сил пытаюсь загрузить модули так, как вы предложили, модули загружаются, но их конфигурация, похоже, не работает, и когда я пытаюсь перейти к маршруту какого-либо динамически загружаемого модуля, это дает ошибку 404, которая сообщает нам config не загружается или работает неправильно, какие-либо предложения по этому поводу? - person Haris Mehmood; 24.07.2017
comment
Рад помочь, но мне нужно немного больше информации. Я склонен справляться с такими ситуациями методом исключения, а что пробовали вы? Если следовать примеру, который я опубликовал, как выглядит объединенная конфигурация? Загружена ли какая-либо конфигурация модуля? - person adamdyson; 25.07.2017
comment
Спасибо за ваш ответ. Я разместил его как вопрос, не могли бы вы изучить его? С уважением, stackoverflow.com/ вопросы/45295059/ - person Haris Mehmood; 25.07.2017
comment
Хорошо, теперь я понимаю, что вы задаете совершенно другой вопрос, чем мой ответ здесь. Если я найду решение вашего вопроса, я дам вам знать. - person adamdyson; 25.07.2017
comment
Прежде чем я углублюсь в это, вы можете сначала попробовать отключить кеш конфигурации и модуля, а также добавить обновление диспетчера служб: $serviceManager-›setAllowOverride(true); $serviceManager-›setService('config', $configuration); $serviceManager-›setAllowOverride(false); - person adamdyson; 25.07.2017

Вы можете получить его от MvcEvent

$locator = $event->getTarget()->getServiceLocator()->get('YourObject')

Если у вас нет доступа к событию, вы можете установить событие как свойство класса модуля при начальной загрузке, а затем использовать его в своем методе инициализации всякий раз.

 public function onBootstrap($event) {
        $this->setMvcEvent($event);
 }

function init(\Zend\ModuleManager\ModuleManager $moduleManager)
{
    $locator = $this->mvc_event->getTarget()->getServiceLocator()->get('YourClass');
    $moduleManager->getEventManager()->attach(
            MvcEvent::EVENT_BOOTSTRAP, array(ClassX, 'StaticMethodOfClassX'), 20000);
}
person STLMikey    schedule 22.10.2013
comment
Спасибо за ваш ответ, но, пожалуйста, прочитайте мой вопрос, я написал Очевидно, что Module::onBootstrap не вариант, и, как вы знаете, я не могу получить доступ к MVCEvent в методе Module::init. - person ; 23.10.2013

Используете ли вы ZfcBase в своем приложении? У AbstractModule есть метод boostrap (не onBootstrap), который выполняется этим обработчиком событий в методе инициализации.

$sharedManager->attach('Zend\Mvc\Application', 'bootstrap', function($e) use ($instance, $moduleManager) {
    $app = $e->getParam('application');
    ...
    $instance->bootstrap($moduleManager, $app);
});

Конечно, вы можете использовать этот подход и без ZfcBase.

Затем вы можете реализовать Zend\ServiceManager\ServiceLocatorAwareInterface:

public function bootstrap(\Zend\ModuleManager\ModuleManager $moduleManager, \Zend\Mvc\ApplicationInterface $app){
    $this->setServiceLocator($app->getServiceManager());
    parent::bootstrap($moduleManager, $app);
}

public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator){
    $this->_serviceLocator = $serviceLocator;
    return $this;
}

public function getServiceLocator(){
    return $this->_serviceLocator;
}
person mellors    schedule 20.03.2014

Может быть, чуть позже, но надеюсь, что это поможет кому-то еще. В момент инициализации в Service Manager не так много сервисов, но вы можете получить к нему доступ:

public function init(ModuleManager $moduleManager)
{
    $sm = $moduleManager->getEvent()->getParam('ServiceManager');
    $applicationConfig = $sm->get('applicationconfig');
    var_dump($applicationConfig['modules']);
}

В этом случае мы извлекаем имена модулей.

person itrascastro    schedule 21.01.2015

Это лучшая идея.

модуль класса

public function onBootstrap(MvcEvent $e)
{

    $sm = $app->getServiceManager();
    $config = $sm->get('config');

и это все.

person PawelC    schedule 28.02.2015