Как создать виджет на Symfony

Часто спрашивают есть ли аналоги виджетов в Symfony, как например в Yii и как их можно реализовать? Для тех кто не знает что такое виджет: виджеты - это многоразовые блоки, обычно используются в видах (вьюхах), чтобы добавить интерфейсу какие-то элементы. C помощью виджетов обеспечивается ООП-подход к повторному использованию кода пользовательского интерфейса.

В качестве примера мы будем создавать виджет, который выводит все категории в сайдбар. Для начала, нам понадобится сам Symfony 4 или 5 версии (чем свежее тем лучше), а так же нам будет нужен шаблонизатор Twig который по умолчанию есть в коробке.

Сразу возникает где мы будем хранить классы виджетов? Все виджеты удобно хранить в папке /src/Widget. Сразу же создаём в этой папке файл CategoriesWidget.php (это название виджета). Так же допустим, что сущность для категорий у вас уже есть.

Пример кода виджета:

<?php
namespace App\Widget;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 
class CategoriesWidget extends AbstractController
{
    private $em;
 
    public function __construct() 
	{
        $this->em = $this->getDoctrine()->getManager();
    }
 
    public function show() 
	{
        $categories_rep = $this->em->getRepository(\App\Entity\Categories::class);
        $categories = $categories_rep->findAll();
        return $this->render('widgets/category.html.twig',['categories' => $categories]);
    }
}

как вы видите виджет - это обычный контроллер в Symfony, который ничем не отличается от тех контроллеров которые вы обычно создаете. Однако как нам его использовать в сайдбаре?

Теперь нам нужно создать папку в которой будут лежать шаблоны для наших виджетов. Создаём templates/widgets и там же создаем файл category.html.twig.

Пример файла:

<aside class="widget widget_list_categories">
    <h3 class="widget-list-title">
        <span>Лучшие рубрики</span>
    </h3>
    <ul>
        {% for cat in categories %}
            <li class="item{{ cat.id }}">
                <a href="{{ path('category', {slug: cat.slug}) }}">{{ cat.name }}</a> ({{ cat.countPosts }})
            </li>
        {% endfor %}
    </ul>
</aside>

Теперь нам осталось только вывести нужный виджет в нужном месте. Идём, например, в base.html.twig и создаём там сайдбар, в котором будем рендерить наш виджет категорий.

Пример:

<div id="secondary" class="sidebar widget-area">
    {{ render(controller('App\\Widget\\CategoriesWidget::show')) }}
</div>

Вот и все что надо сделать для того что бы начать использовать виджеты в своих проектах. Все оказалось довольно просто!