Введение
В данной статье речь пойдет о том, как организовать код так, чтобы иметь возможность вставлять в разных twig-шаблонах одинаковые блоки (виджеты). Рассмотрим несколько вариантов реализации такого механизма.
WidgetController
Данный способ предполагает, что виджеты являются методами контроллера. Пример
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class WidgetController extends AbstractController
{
public function widget(): Response
{
return $this->render('widget.html.twig', ['number' => rand()]);
}
}
В шаблоне блок можно отрисовать так:
{{ render(controller('App\\Controller\\WidgetController:widget')) }}
Данный способ описывается в документации symfony и содержит следующий недостаток
Rendering embedded controllers is “heavier” than including a template or calling a custom Twig function. Unless you’re planning on caching the fragment, avoid embedding many controllers.
Include
Самый просто механизм вставки блоков без доп. логики
{% include 'widget.html.twig' with {number:random()} %}
Twig extension
С помощью данного метода можно реализовать логику получения данных, аналогичную первому методу, но без оверхеда, связанного с созданием подзапроса. Пример:
<?php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class WidgetExtension extends AbstractExtension
{
/** @var \Twig_Environment */
private $twig;
/**
* @param \Twig_Environment $twig
*/
public function __construct(\Twig_Environment $twig)
{
$this->twig = $twig;
}
/**
* @return array
*/
public function getFunctions(): array
{
return [
new TwigFunction('lucky_widget', [$this, 'renderLuckyWidget'], ['is_safe' => ['html']]),
];
}
/**
* @return string
* @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax
*/
public function renderLuckyWidget(): string
{
return $this->twig->render('widget.html.twig', ['number' => rand()]);
}
}
Сравнение
Чтобы сравнить, какой из перечисленных выше способов отработает быстрее, создадим небольшой проект и измерим с помощью простого бенчмарка ab скорость отрисовки. Ниже представлен график времени отрисовки для всех трех методов.
Мы видим, что лучше всего себя показал twig extension. Однако, если мы обратим внимание на абсолютное значение времени отрисовки, выигрыш не кажется таким существенным.