За что я люблю Yii+Twig: динамическое подключение нужных скриптов

Навеяно вот этой статьёй.

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

Так уж сложилось, что в качестве шаблонизатора мне полюбился Twig.

Вот прямо как влитой мне — сначала на CodeIgniter, потом я подружил его с Yii через чуть-чуть подломанное мною расширение (ссылка на которое в конце статьи)

Одна из тысяч крутых его фич это наследование шаблонов, вроде того, что ниже:

layout.twig

<html>
<head><title>{% block title %}{% endblock %}</title></head>
<body>
<h1>Привет, Хабрахабр!</h1>
{% block content %}{% endblock %}
</body>
</html>


index.twig

{% extends 'layout.twig' %}
{% block title %}Меняю заголовок страницы{% endblock %}
{% block content %}Как бодрость духа?{%endblock%} 


В итоге при рендере нашего index.twig мы ставим тайтл и делаем приветствие более неформальным.

Теперь было бы неплохо прикрутить скрипты и остальное.
Я делаю это следующим образом — папки css,img,js у меня находятся внутри папки assets, которая уже в свою очередь лежит в папке с темой оформления (если публиковать отдельно css и img то поломаются относительные ссылки в css). В основном шаблоне я делаю так:
{% set assetsDir = Yii.app.publishFile('assets')  %}
{% call Yii.app.clientScript.registerScriptFile( assetsDir~'/js/chosen.jquery.min.js' ) %}
{% call Yii.app.clientScript.registerCssFile( assetsDir~'/css/screen.css', 'screen') %}


publishFile был добавлен как обертка над assetManager, для поддержки относительных путей с учетом выбранной темы оформления. Т.е. конструкция Yii.app.publishFile('assets') опубликует папку assets из каталога текущей темы — мне удобно.

В какой-то момент решив подключить дополнительный скрипт к конкретному представлению я в его twig-файле делаю всего лишь
{% call Yii.app.clientScript.registerScriptFile( assetsDir~'/js/myscript.js' ) %} 


В итоге я получаю замечательно читающийся (мне, во всяком случае) шаблон — я сразу вижу где чего наподключалось.

layout.twig

{% set assetsDir = Yii.app.publishFile('assets')  %}
{% call Yii.app.clientScript.registerScriptFile( assetsDir~'/js/chosen.jquery.min.js' ) %}
{% call Yii.app.clientScript.registerCssFile( assetsDir~'/css/screen.css', 'screen') %}
<html>
<head><title>{% block title %}{% endblock %}</title></head>
<body>
<h1>Привет, Хабрахабр!</h1>
{% block content %}{% endblock %}
</body>
</html>


index.twig

{% extends 'layout.twig %}
{% block title %}
{% call Yii.app.clientScript.registerScriptFile( assetsDir~'/js/myscript.js' ) %} 
Меняю заголовок страницы
{% endblock %}
{% block content %}Как бодрость духа?{%endblock%} 


В контроллере дергаем за $this->render('index') и вуаля!

Для меня очень важным в таком подходе является то, что подключение ресурсов я контролирую непосредственно в представлениях.
Нюанс — в шаблонах, расширяющих другой шаблон, переменные, определенные родительским шаблоном будут доступны только в конструкциях {% block %}{% endblock %}

Ссылка на использованный twig-extension для Yii: https://github.com/yiiext/twig-renderer

Правда он у меня, как я писал выше, подломан — из коробки не хотел дружить с темами, плюс вызывать процедуры, не возвращающие значений, мне проще было конструкцией
{% call procedurename() %}
чем трудночитаемой
{{ void( procedurename() ) }}, поэтому я накидал небольшое расширение для twig.
Поделиться публикацией

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 28

    –3
    Шаблоны можно использовать только, если их может редактировать конечный пользователь. В других случаях это бесполезная трата ресурсов.

    {% for item in navigation %}
      {% call procedurename(item) %}
    {% endfor %}
    

    <?php foreach($navigation as $item): ?>
      <?= procedurename($item) ?>
    <?php endforeach ?>
    
      +2
      Само собой. Не усмотрел, где это утверждение противоречит тому, что я написал.
      Я так понял два куска кода это пример, что эти вещи можно сделать без шаблонизатора?
        0
        Функцию call глупо давать конечному пользователю, поэтому решил, что это для разработчиков шаблоны.
        0
        А теперь давайте пример с наследованием, автоматическим экранированием и сандбоксом. Шаблоны компилируются в нативный php, так что оверхед не такой большой, как вам кажется. Если же в вашем приложении шаблоны действительно являются узким местом, попробуйте Си расширение.
          0
          Кстати да. Когда начинал им пользоваться — его еще не было. Пару-тройку месяцев назад наткнулся на сайте на информацию о нативном расширении, был приятно удивлен.
            0
            Ну, строго говоря, сандбокс — это очень ограниченная область применения (которую, собственно, и имел в виду первый комментатор), а остальное делается просто.

            Пока из реальных проблем нейтива я столкнулся только с одной — автоискейпинг для свойств объектов. В то время как для скаляров и массивов он реализуется элементарно, для объектов это действительно — головная боль.
            0
            Шаблонизатор прямо как от Django.
            Я встречал еще другие шаблонизаторы(для php и nodejs) которые оч похожи на джанговские.
            Вообще оч люблю Django шаблоны, хотя чаще пользуюсь Jinja2(он похож на джанговский но быстрее и еще некоторые различия).
            Раз уж вам так нравится Twig, советую обратить свое внимание на Django или Flask)
              0
              Упс, хотел написать в общую.
                +1
                Представьте себе, я как раз этому очень обрадовался, начав обхаживать Python и Django. Сейчас на фриланс полностью уйду и буду шевелить это дело — Python в первом приближении нравится, Django тоже.
                  0
                  Автор Twig, Fabien Potencier, в общем-то и не скрывал, где черпал вдохновение. Да, это порт шаблонизатора Django. С некоторыми изменениями, конечно. Например, в Twig теги комментария {# #} работают на группу строк, а в Django только на одну. Полагаю, что и других изменения полно, так как Twig развивается весьма активно.
                    0
                    Ну в Django если надо на много строк то {% comment %}многабукаф и строк{% endcomment %}
                    мне так кажется даже лучше и нагляднее.
                    Я стараюсь и блоки тоже более наглядно закрывать. Например, такой блок {% block content %} проще закрывать так {% endblock %}, а я же закрываю так {% endblock content %} чтобы нагляднее было какой именно блок закрывается.
                    Я чаще пользую Jinja2 и с Django и c Flask. Там тоже {# тут много строк и можно {%%} #}
                    У меня один из любимых шаблонизаторов это у Tumblr =)
                  0
                  Ваше заявление касается только случая, когда шаблоны обрабатываются в runtime, однако если шаблоны компилируемые (как в Smarty или как в Twig), то с большой вероятностью Вы не сможете вручную сделать исполняемый код быстрее, чем код скомпилированного шаблона. Я уже не говорю о кэшировании, которое в случае шаблонизатора добавляется буквально двумя строками кода и сводит на нет «преимущества» приведённого Вами лапшекода.
                    0
                    Раз мы говорим о Yii то там кеширование добавляется буквально двумя строчками кода в любом случае. Да и работа с php шаблонами там достаточно сильная.
                      0
                      sdevalex имел ввиду шаблоны вообще, если я правильно понял… А в Yii кэширование куска шаблона тоже можно сделать двумя строчками кода?
                        0
                        Там есть кеширование страницы, куска шаблона, sql запроса, и данных. Конкретно кусок шаблона кешируется так
                        <?php if($this->beginCache('cacheKey')) { ?> <?php $this->endCache(); } ?>
                        К слову в Yii встроен шаблонизатор Prado и соответственно есть сильная его поддержка. К примеру аналог кеширования фрагмента будет таким.
                        <cache:cacheKey> </cache:profile >

                          0
                          Но конкретно для Yii я не вижу необходимости использовать шаблонизатор. Разве что шаблоны будут редактировать пользователи.
                    0
                    Вы просто отчаянную ерунду написали. Умудрились наделать ошибок практически в каждой строчке.

                    1. Шаблоны нужны не для редактирования пользователем, а для разделения бизнес-логики и логики отображения. Чтобы одни и те же данные можно было выводить в разном виде, не трогая код приложения. Пример: один и тот же движок стоит на разных сайтах. Если используется шаблонизация, то обновление движка сводится к простой заливке кода. Если шаблонизация не используется — под каждый сайт движок надо редактировать отдельно. ещё пример: одно и то же приложение может возвращать как HTML, так и JSON. Если для первого использовался шаблонизатор, то добавить второе можно не трогая код. В противном случае код придется переписывать (и дублировать).

                    2. В случае с Twig никакой бесполезной траты ресурсов нету — шаблон транслируется в тот же самый РНР код.

                    3. Приведённый пример РНР кода тоже вполне может быть шаблоном (что повсеместно и используется)

                    4. Мог бы быть, точнее. Но не является, из-за непонятной функции procedurename(), которая, если что-то выводит и реализована в коде приложения, убивает идею шаблонизации на корню.

                    5. Пост был совсем не об этом.

                    0
                    Ссылка на использованный twig-extension для Yii некорректная.
                      0
                      Спасибо, поправил
                      0
                      А вообще было круто написать свой экстеншен для Twig который бы делал {% css 'url' %}
                        0
                        Там дело пяти минут — могу сделать. Зачем только? Yii.app.clientScript.registerCssFile долго писать?
                          0
                          Да ;)
                            0
                            может вы и автолоадом в пхп не пользуетесь? =: О только инклуды! только хардкор!
                              0
                              Пользуюсь-пользуюсь :) Просто уровень лени, толкающий на автоматизацию, у всех разный. У меня он таков, что конструкции, описанные в примере, меня не раздражают — мне удобно их писать, удобно их читать.
                              А {% css 'url' %} я для вас обязательно напишу — мне не сложно. Могу даже вдогонку и {% js 'url' %} написать
                            0
                            Если устроит {{ css('url') }}, можно обойтись и макросом.
                            0
                            Не силён в Yii, объясните, чем не подходит такой вариант:

                            layout.html.twig
                            {% block javascripts %}
                            <!-- global js files -->
                            {% endblock %}
                            


                            page.html.twig
                            {% extends "layout.html.twig" %}
                            {% block javascripts %}
                                {{ parent() }}
                                <!-- page js files -->
                            {% endblock %}
                            
                              0
                              Конечно, можно сделать и так.
                              У использования clientScript есть некоторые преимущества, такие как возможность организовать обработку подключенных файлов перед их выводом (навскидку приходит на ум склеивание js и css в единые файлы), выбор места подключения js-файла — в head, в начало body, в конец body. Также можно определить именованные пакеты файлов и подключать их одним вызовом.
                              Я привык пользоваться clientScript, мне удобно.

                              0
                              В очередной раз так и не понял зачем в Yii нужен twig, все что описано и так довольно легко реализуется, в yii в начале выполняется шаблон страницы(в этот момент можно поменять layout), а после — layout, оба выполняются из контроллера и имеют к нему доступ, тот же заголовок можно задавать и выводить через $this->title, блоки реализованы в виде CBaseController::beginClip, вложенные layout присутствуют.

                              Сложность php шаблонов, имхо, надуманная проблема, переносимость шаблонов между системами крайне редко нужна, а если и понадобится — подобный фукционал можно легко реализовать.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое