Encodera

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

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

Оглавление

Свои помощники шаблонов

Встроенные помощники шаблонов — url(), escapeHtml(), partial() — покрывают общие задачи. Когда в шаблонах повторяется своя логика вывода — обрезать текст, оформить дату, показать цену, — её выносят в собственный помощник. Это класс, который вызывают в шаблоне так же, как встроенные: $this->excerpt($text).

Класс помощника

Помощники модуля кладут в module/<Модуль>/src/View/Helper. Создайте папки и файл вручную:

// module/Blog/src/View/Helper/Excerpt.php
namespace Blog\View\Helper;
 
use Laminas\View\Helper\AbstractHelper;
 
class Excerpt extends AbstractHelper
{
    public function __invoke(string $text, int $length = 100): string
    {
        if (mb_strlen($text) <= $length) {
            return $text;
        }
 
        return mb_substr($text, 0, $length) . '…';
    }
}

Класс наследует AbstractHelper, а метод __invoke() выполняется при вызове помощника. Этот помощник сокращает длинный текст до заданного числа символов.

Регистрация

Помощников описывают в разделе view_helpers файла module/Blog/config/module.config.php:

// module/Blog/config/module.config.php
'view_helpers' => [
    'factories' => [
        View\Helper\Excerpt::class => InvokableFactory::class,
    ],
    'aliases' => [
        'excerpt' => View\Helper\Excerpt::class,
    ],
],

Устройство то же, что у помощников контроллера: factories создаёт класс, aliases задаёт имя для шаблонов.

Вызов в шаблоне

<!-- module/Blog/view/blog/post/index.phtml -->
<ul>
    <?php foreach ($this->posts as $post): ?>
        <li>
            <strong><?= $this->escapeHtml($post->title) ?></strong>
            <p><?= $this->escapeHtml($this->excerpt($post->body, 80)) ?></p>
        </li>
    <?php endforeach; ?>
</ul>

Под каждым заголовком появятся первые 80 символов статьи с многоточием. Помощник возвращает обычный текст, поэтому результат оборачивают в escapeHtml().

Помощник, который выводит HTML

Если помощник сам возвращает разметку, экранировать значения нужно внутри него. Другие помощники доступны через getView():

// module/Blog/src/View/Helper/PostLink.php
namespace Blog\View\Helper;
 
use Blog\Model\Post;
use Laminas\View\Helper\AbstractHelper;
 
class PostLink extends AbstractHelper
{
    public function __invoke(Post $post): string
    {
        $view = $this->getView();
 
        return sprintf(
            '<a href="%s">%s</a>',
            $view->url('blog/view', ['id' => $post->id]),
            $view->escapeHtml($post->title),
        );
    }
}

После регистрации с псевдонимом postLink запись <?= $this->postLink($post) ?> выведет готовую ссылку на статью.

Помощник с сервисом

Помощнику можно передать сервис через конструктор — например, ReadingTime из урока о диспетчере сервисов:

// module/Blog/src/View/Helper/ReadingMinutes.php
namespace Blog\View\Helper;
 
use Blog\Service\ReadingTime;
use Laminas\View\Helper\AbstractHelper;
 
class ReadingMinutes extends AbstractHelper
{
    public function __construct(private ReadingTime $readingTime) {}
 
    public function __invoke(string $text): int
    {
        return $this->readingTime->minutes($text);
    }
}

В view_helpers.factories для него указывают ReflectionBasedAbstractFactory::class. Теперь время чтения считают прямо в шаблоне: $this->readingMinutes($post->body).

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

Помощник шаблона — не место для запросов к базе. Вызов таблицы внутри помощника, который стоит в цикле, выполнит запрос для каждой строки списка, и страница станет медленной. Данные готовит контроллер и передаёт в ViewModel, а помощник только оформляет то, что получил.

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

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