Свои помощники шаблонов
Встроенные помощники шаблонов — 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, а помощник только оформляет то, что получил.