Как стать автором
Обновить

ZF2 + Blitz templates

PHP *Zend Framework *
Здравствуйте, разлюбезные мои хабровчане. А ежели кто из вас веб-разработкой на PHP занимается, то и вообще добро пожаловать. Я тут давеча стал смотреть на разные фреймворки… Развелось их у нас в ПеХаПе — страсть. Яблоку негде упасть, как говорят блондинки.



Вспомнилось тут, что когда-то давно (когда DOM-деревья были большими, а юникод однобайтовым) грешным делом внес махонький коммит в Zend Framework (тогда еще только 1-я версия была). Дай думаю, посмотрю — чем живет, чем дышит этот Зенд сегодня. Смотрю — вырос-то как… возмужал… А я его вот такусеньким помню… Стал читать, что дальше будет, а еще статью про PSR-7, HTTP Messages и их реализацию в PHP. Батюшки-светы! Надо дальше смотреть, надо учиться, учиться и учиться. А то придет молодая шпана, да как сотрет меня с лица Земли:



Все пришлось учить сызнова. Покряхтел, прошел Getting Started Quest Guide, задумался. Что-то мне во всем этом не понравилось. Может, мрачные слова «Skeleton Application» в верхней части? Или то, что конфиг для Nginx пришлось самому писать (что это они мне своей Апачьей харей в морду тычут?). Да нет, не то…

О! Там ведь в ZF2 шаблонизатор на PHP!

Tired of Spaghetti code? Try Blitz!


За годы работы в Badoo шаблоны Blitz стали привычными и родными. Надо их сюда срочно прикрутить. Погуглил — нету. Что за черт?? (наверное, плохо гуглил?) В общем, начистил скальпель XDebug, взял вату, спирт и огурец, и стал препарировать.



Пациентом выступило приложение-обучалка. Точнее, его форк.

Тэк-с, посмотрим, посмотрим… Какая здоровая печень у пациента, вы не находите, коллега? Хоть в гроб клади… Вот ее-то мы и пересадим. Под печенью я подразумеваю реализацию 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. Может, профессионалы знают более толковый путь? Обсудим?
Теги:
Хабы:
Всего голосов 11: ↑5 и ↓6 -1
Просмотры 7.6K
Комментарии Комментарии 5