Как да получа препратка към мениджъра на услуги в метода за инициализация на модула (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'), но да я взема от мениджъра на услугата. Проблемът ми е, че не знам как да получа препратка към мениджъра на услуги в метода init на модула. Някаква помощ? или това е невъзможно в ZF2 в момента? Какъвто и вариант на тази схема или мнение също ще бъде оценен;)

РЕДАКТИРАНЕ:

Ще изясня „Очевидно Module::onBootstrap не е опция“, защото може да не е толкова тривиално;)

Методите на модули Module::onBootstrap се изпълняват, когато се задейства събитие MvcEvent::EVENT_BOOTSTRAP, но прикачването на метода Module::onBootstrap на всеки модул към това събитие зависи от реда, в който модулите са били заредени. Поради това редът, в който ще бъде изпълнен конкретен Module::onBootstrap метод, зависи от това какви други модули съществуват и как другите модули влияят на реда, в който този конкретен модул ще бъде зареден. Освен това, всеки слушател, прикачен към събитието MvcEvent::EVENT_BOOTSTRAP с приоритет, по-голям от 1, ще бъде изпълнен преди който и да е метод на модул Module::onBootstrap, например слушателят ViewManager::onBootstrap. И така, да постигна това, което искам

Трябва да се изпълни някакъв код, преди да се изпълни който и да е MvcEvent::EVENT_BOOTSTRAP слушател

modules 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 показва как да манипулирате обединената конфигурация, но в този конкретен момент Service Manager е празен, което прави невъзможно извличането на неща като адаптери на бази данни и т.н.

Решение:

Във вашия клас модул внедрете интерфейса 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
Здравей adamdyson, всъщност се боря да заредя модулите по начина, който предложи, модулите са заредени, но изглежда, че конфигурацията им не работи и когато се опитам да отида на маршрут на някакъв динамично зареден модул, той дава грешка 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')

Ако нямате достъп до събитието, можете да зададете събитието като свойство на класа на модула при стартиране и след това да го използвате във вашия init метод винаги.

 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), който се изпълнява от този манипулатор на събития в метода init

$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