Вспомнилось тут, что когда-то давно (когда DOM-деревья были большими, а юникод однобайтовым) грешным делом внес махонький коммит в Zend Framework (тогда еще только 1-я версия была). Дай думаю, посмотрю — чем живет, чем дышит этот Зенд сегодня. Смотрю — вырос-то как… возмужал… А я его вот такусеньким помню… Стал читать, что дальше будет, а еще статью про PSR-7, HTTP Messages и их реализацию в PHP. Батюшки-светы! Надо дальше смотреть, надо учиться, учиться и учиться. А то придет молодая шпана, да как сотрет меня с лица Земли:
Все пришлось учить сызнова. Покряхтел, прошел Getting Started
О! Там ведь в ZF2 шаблонизатор на PHP!
За годы работы в Badoo шаблоны Blitz стали привычными и родными. Надо их сюда срочно прикрутить. Погуглил — нету. Что за черт?? (наверное, плохо гуглил?) В общем, начистил
Пациентом выступило приложение-обучалка. Точнее, его форк.
Тэк-с, посмотрим, посмотрим… Какая здоровая печень у пациента, вы не находите, коллега? Хоть в гроб клади… Вот ее-то мы и пересадим. Под печенью я подразумеваю реализацию RendererStrategy из Zend View Quick Start. Берем класс AcceptStrategy и копируем к себе. Назовем копию, как водится, Полуэкт. Шучу, назовем Application\View\RenderingStrategy. Почему не BlitzRenderingStrategy? Да, собсно, она создает и настраивает наш движок рендеринга, а значит, она же будет, например, настраивать рендеринг JSON, в случае соответствующего запроса. Так что вот.
В получившемся классе я ампутировал свойства «xxxRenderer» — а зачем они нам сразу нужны? Ну и чтобы иметь под рукой зендовский ServiceManager, решил передавать его в конструкторе:
/**
* @param ServiceManager $sm
*/
public function __construct(ServiceManager $sm = null)
{
$this->sm = $sm;
}
selectRenderer() и injectResponse() пришлось переписать. Вот до чего доходит!
/**
* @param ViewEvent $e
* @return \Zend\View\Renderer\RendererInterface
*/
public function selectRenderer($e)
{
$model = $e->getModel();
if ($model instanceof JsonModel) {
return $this->sm->get(JsonRenderer::class);
}
return $this->sm->get(BlitzRenderer::class);
}
/**
* @param \Zend\Mvc\MvcEvent $e The MvcEvent instance
* @return void
*/
public function injectResponse($e)
{
$renderer = $e->getRenderer();
$response = $e->getResponse();
if ($renderer instanceof JsonRenderer) {
// JSON Renderer; set content-type header
$headers = $response->getHeaders();
$headers->addHeaderLine('content-type', 'application/json');
}
// Inject the content
$response->setContent($e->getResult());
}
Что-то давно картинок не было.
Вот. Уже и целый класс сделал! Но и этого оказалось мало! Нужно еще, чтобы наш «модуль» (слово-то какое — мооодуль) знал о том, что мы ему готовим! Нет, каков гусь, а?! Это все происходит в классе Application\Module
/**
* @param \Zend\Mvc\MvcEvent $e The MvcEvent instance
* @return void
*/
private function registerRenderingStrategy($e) {
$app = $e->getTarget();
$locator = $app->getServiceManager();
$view = $locator->get(\Zend\View\View::class);
$renderingStrategy = $locator->get(RenderingStrategy::class);
// Attach strategy, which is a listener aggregate, at high priority
$view->getEventManager()->attach($renderingStrategy, 100);
}
public function getServiceConfig()
{
return array(
...
'factories' => array(
RenderingStrategy::class => function ($sm) {
/** @var ServiceManager $sm */
return new RenderingStrategy($sm);
},..
),
);
}
Ну и немного изменить onBootstrap() в модуле приложения:
$eventManager->attach('render', function($e) {
/** @var \Zend\Mvc\MvcEvent $e */
return $this->registerRenderingStrategy($e);
}, 100);
Что еще добавить? Я решил, что негоже Blitz-шаблоны сохранять с расширением .phtml и до кучи поменял конфиг:
'view_manager' => array(
...
'default_template_suffix' => 'blitz.html',
),
Ну, еще пришлось чуууть-чуть изменить код контроллера там, где во вьюху передается результат выборки из БД: Blitz не поддерживает все эти новомодные итераторы, ему массивы подавай (деды наши без итераторов программировали, и мы будем! Правда, fisher?) Попутно обнаружилось, что если вызвать toArray() у экземпляра ResultSet, то он будет вызывать тот же toArray() на каждом ряде. Пришлось дополнить модель Album методом toArray(). А, ну еще пришлось шаблоны перевести на Blitz и сохранить с суффиксом «blitz.html».
Даже не знаю, насколько плох такой способ интеграции шаблонного движка в ZF2. Может, профессионалы знают более толковый путь? Обсудим?
Комментарии (5)
Arilas
05.10.2015 10:54+3Для inject'а ServiceLocator'а достаточно было использовать ServiceLocatorAwareInterface либо ServiceManagerAwareInterface. В конфиг засовывать функции колбеки — не очень (getServiceConfig). Конфиг должен быть таким, чтобы легко кешировался, поэтому, если заимплементили один из интерфейосв выше, могли бы в module.config.php добавить:
'service_manager' => [
'invokables' => [
BlitzStrategy::class => BlitzStrategy::class
]
].
Зарегистрировать стратегию можно проще:
view_manager:
strategies:
BlitzStrategy
В конфиге.
А вообще наконец, первая нестандартная статья про ZF2.crocodile2u
05.10.2015 11:50Спасибо, ценные рекомендации, я пока не дошел до «invokables» и «view_manager/strategies».
Arilas
05.10.2015 12:27В ZF2 очень много интересных вещей, которые очень хорошо зарыты в коде, и в доке достаточно сложно понять, что зачем.
К примеру то, что есть множество разных ServiceManager'ов, и для них отдельные сервисы и поведение можно задать. Те же контроллеры бывают не только «invokables» но также можно использовать Фабрики и Абстрактные фабрики для них.
Также есть так называемые «loaders» — предназначены для инициализации любого сервиса (к примеру реализующего ServiceLocatorAwareInterface)
Вообще когда-то писал рендер вьюшек в pdf файл, даже модуль есть: packagist.org/packages/krona/wkhtml-module Но это очень давно было уже
uLow
Своеобразная подача.
По материалу — с одной стороны, обозначены места где и что делалось.
С другой — почему делались именно такие изменения — не понятно.
То есть подача материала аля «для самых маленьких», а сам материал 18+.
crocodile2u
Эээ, ну не знаю, это то, что я сделал за пару часов после 3-4 часов изучения ZF2. Как бы не понимаю, что тут подробнее расписывать. К тому же результат-то лежит на гитхабе — бери да смотри, да пользуйся ;-)