Zend Framework 2 - Приложения / Модули / Сервис-менеджеры - Oh My
Я только начал изучать Zend Framework 2 как давний разработчик Zend Framework 1. У меня возникли небольшие проблемы, когда я оборачиваюсь вокруг новой терминологии.
Назад в ZF1, если бы я хотел создать регистратор, который был бы глобальным для приложения, я бы добавил конфигурацию в файл application.ini, и загрузчик инициализировал бы его как ресурс (надеюсь, я правильно это говорю). Итак, с любого из моих контроллеров модулей я мог получить доступ к логгеру через ресурсы начальной загрузки.
Введите ZF2, Модули немного другой зверь, они самодостаточны, но я немного смущен тем, как они взаимодействуют с приложением. Мне кажется, что именно здесь ServiceManager вступает в игру. Моя цель состоит в том, чтобы иметь мой Модуль (не контроллер, а сам модуль), чтобы проверить, определено ли в Приложении логгер и, если он есть, использовать этот логгер во всем модуле. Если приложение не определяет регистратор, я хочу, чтобы модуль определил регистратор для регистрации всего модуля.
Этот вопрос также относится и к базам данных, скажем, я хочу, чтобы приложение определяло логику соединения с базой данных, в то время как я хочу, чтобы модуль определял логику требуемых таблиц. Как именно я это настраиваю и как / где я могу узнать, есть ли уже ресурс базы данных, определенный в Приложении.
Примечание: я прошел Quickstart Роба Аллена (достаточно информации и единственный ресурс, который я обнаружил, что при этом не хватает неизвестности), а также ZF2 (readthedocs), и уже погуглил тонны. Что я обнаружил, так это то, что информация, как правило, очень неясна, когда речь идет о том, "куда" уходят определенные кусочки головоломки.
2 ответа
То, что вы знаете из Zend Framework 1.x, является "Ресурсом приложения".
Понятие "ресурс приложения" заменено в Zend Framework 2 на так называемые "сервисы" (введение здесь)
Другое изменение - сами модули. В ZF1 модуль был в основном подразделом вашего приложения, который обрабатывал некоторые запросы. Это больше не верно в ZF2: если ваш модуль определяет сервис или контроллер, то теперь он доступен для всех приложений. Есть хорошее введение в некоторые различия между ZF1 и ZF2 от Гэри Хокина.
Но в любом случае, модули НЕ являются автономными. Их следует разрабатывать в изолированной среде и с как можно меньшим количеством зависимостей, но они обеспечивают функциональность перекрестных проблем, которая затрагивает все ваше приложение.
Для вашего конкретного случая с регистратором, я полагаю, что ваш модуль всегда определяет регистратор и использует его. Что можно сделать для определения логгера условно:
class MyModule
{
public function onBootstrap($e)
{
// $e->getTarget() is the \Zend\Mvc\Application
$sm = $e->getTarget()->getServiceManager();
if (!$sm->has('some-logger-name')) {
$sm->setFactory('some-logger-name', function ($sl) {
return new MyLogger($sl->get('some-db'));
});
}
}
}
После этого вы сможете использовать "some-logger-name" во всех своих приложениях.
Другой подход состоит в том, чтобы просто определить службы ведения журнала и позволить другим модулям или конфигурациям переопределить его позже:
class MyModule
{
public function getConfig()
{
return array(
'service_manager' => array(
'factories' => array(
'some-logger-name' => 'My\Logger\Factory\ClassName'
),
),
);
}
}
То же самое достигается с getServiceConfig
, который менее гибок и не может быть кэширован, но имеет более высокий приоритет над getConfig
(позволяет переопределять) и позволяет также определять фабрики обслуживания как замыкания:
class MyModule
{
public function getServiceConfig()
{
return array(
'factories' => array(
'some-logger-name' => function ($sl) {
return new MyLogger($sl->get('some-db'));
},
),
);
}
}
Затем вы могли бы даже определить ключ конфигурации, который должен использоваться, чтобы решить, какой регистратор (имя службы) использовать.
Концепция с модулями и конфигурациями заключается в том, что "последний модуль выигрывает", поэтому вы можете определить услугу 'some-logger-name'
либо в вашем модуле, либо в любом модуле, загруженном до него.
Те же понятия применимы и к вашему соединению с БД.
Как видите, переход к услугам уже дал вам определенную степень свободы.
Имейте в виду, что это не то, что "Приложение" определяет что-то для вас: модули определяют ваши сервисы / конфиги / события и т. Д.... Тогда работающее приложение представляет собой совокупность всех этих вещей.
Я думаю, что, особенно в случае с журналированием, есть, может быть, даже лучше, конечно, более инкапсулированный способ, чем использование ServiceManager
, ZF2 по сути является управляемой событиями средой, и функциональность, которая позволяет эту управляемую событиями архитектуру, может быть использована в наших интересах. Ведение журнала является прекрасным примером для этого. Вместо того, чтобы определять фабрику, вы должны только прикрепить событие регистратора, которое может быть запущено из любого места в вашем приложении.
Прикрепить log
слушатель событий в вашем Module.php
:
public function onBootstrap(MvcEvent $e)
{
//setup some $logger
$sharedManager = $e->getApplication()->getEventManager()->getSharedManager();
$sharedManager->attach('*', 'log', function($e) use ($logger) {
/** @var $e MvcEvent */
$target = get_class($e->getTarget());
$message = $e->getParam('message', 'No message provided');
$priority = $e->getParam('priority', Logger::INFO);
$message = sprintf('%s: %s', $target, $message);
$logger->log($priority, $message);
});
}
Затем запустите его из любого места в вашем приложении, например, из контроллера:
$this->getEventManager()->trigger('log', $this, array(
'priority' => \Zend\Log\Logger::INFO,
'message' => 'just some info to be logged'
));