Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Шаблоны

Шаблон — файл с расширением .phtml, в котором HTML смешан с короткими вставками PHP. Шаблон принадлежит блоку: макет говорит, где стоит блок, а шаблон — как он выглядит.

Где лежат шаблоны

Шаблоны витрины находятся в папке view/frontend/templates модуля, шаблоны панели управления — в view/adminhtml/templates. Файл создают вручную. В макете шаблон указывают как Acme_Hello::greeting.phtml; вложенную папку пишут после двоеточий: Acme_Hello::review/list.phtml.

Простой шаблон

Замените содержимое файла из прошлого урока:

<!-- app/code/Acme/Hello/view/frontend/templates/greeting.phtml -->
<div class="hello-greeting">
    <h2><?= $escaper->escapeHtml(__('Здравствуйте!')) ?></h2>
</div>

На странице /hello появится заголовок «Здравствуйте!». Конструкция <?= ... ?> выводит значение, функция __() делает строку переводимой, а $escaper->escapeHtml() обезвреживает спецсимволы HTML.

Переменные шаблона

В любом шаблоне Magento уже есть две переменные:

ПеременнаяЧто это
$blockБлок, которому принадлежит шаблон
$escaperОбъект для безопасного вывода

Чтобы редактор кода подсказывал методы, в начале шаблона пишут комментарии с типами:

<!-- app/code/Acme/Hello/view/frontend/templates/greeting.phtml -->
<?php
/** @var \Magento\Framework\View\Element\Template $block */
/** @var \Magento\Framework\Escaper $escaper */
?>

Значения из макета

Блоку можно передать значение прямо в макете — в разделе arguments:

<!-- app/code/Acme/Hello/view/frontend/layout/hello_index_index.xml -->
<block name="hello.greeting" template="Acme_Hello::greeting.phtml">
    <arguments>
        <argument name="shop_name" xsi:type="string">Acme</argument>
    </arguments>
</block>

В шаблоне значение читают методом getData():

<!-- app/code/Acme/Hello/view/frontend/templates/greeting.phtml -->
<h2><?= $escaper->escapeHtml(__('Добро пожаловать в %1!', $block->getData('shop_name'))) ?></h2>

После bin/magento cache:clean заголовок станет «Добро пожаловать в Acme!». Метки %1, %2 в __() заменяются следующими аргументами.

Условия и циклы

В шаблонах принята запись с двоеточием:

<!-- app/code/Acme/Hello/view/frontend/templates/greeting.phtml -->
<?php $benefits = ['Доставка за 2 дня', 'Возврат 30 дней']; ?>
 
<?php if ($benefits): ?>
    <ul>
        <?php foreach ($benefits as $benefit): ?>
            <li><?= $escaper->escapeHtml($benefit) ?></li>
        <?php endforeach; ?>
    </ul>
<?php endif; ?>

Шаблон выведет список из двух пунктов. В следующем уроке массив переедет из шаблона в отдельный класс.

Экранирование

Всё, что выводится на страницу, пропускают через $escaper:

МетодГде применять
escapeHtml()Текст между тегами
escapeHtmlAttr()Значение атрибута
escapeUrl()Адрес в href и src
escapeJs()Строка внутри JavaScript

Ссылки и вложенные блоки

<!-- app/code/Acme/Hello/view/frontend/templates/greeting.phtml -->
<a href="<?= $escaper->escapeUrl($block->getUrl('hello/index/status')) ?>">
    <?= $escaper->escapeHtml(__('Статус')) ?>
</a>
 
<?= $block->getChildHtml('hello.extra') ?>

Метод getUrl() строит адрес страницы, а getChildHtml() выводит блок, вложенный в текущий в макете. Его результат не экранируют — это уже готовый HTML.

Частая ошибка

Значение выводят без экранирования: <?= $review->getAuthor() ?>. Если покупатель ввёл в поле имени тег script, он выполнится в браузерах других посетителей. Любые данные из базы и запроса выводите только через методы $escaper.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.