Symfony 4(Twig)中可重用的动态边栏?

时间:2019-03-10 08:33:53

标签: symfony twig widget symfony4

我最近开始使用Symfony 4,现在我正在使用这个出色的框架创建我的第一个网站。

我有一个侧边栏,应该在大约一半的路线中显示,并且侧边栏的内容应该用数据库中的一些数据填充。

目前,我在所有这些路由中都使用DI,并将注入的存储库的结果传递给该路由的模板(包括我的sidebar.html.twig)。

public function chalupaBatman(FancyRepository $repository)
{
    $sidebarObjects = $repository->getSidebarObjects();
    $this->render('controllername/chalupabatman.html.twig', [
        'sidebarObjects' => $sidebarObjects,
    ]);
}

我想知道是否有一种方法可以避免我在控制器中定义的每条路线。

到目前为止,我在stackoverflow上找到了这个主题。

用户Mvin用完美的方式描述了我的问题,并提供了一些解决方案。

然而,“最佳实践是什么”部分仍然没有答案,该主题来自2017年。因此,解决此问题的方法可能已在Symfony 4中更改。

1 个答案:

答案 0 :(得分:0)

我最终得到了TwigExtension解决方案。我将描述如何实现它,如果你们能提供一些反馈的话,那将是很棒的。 让我知道我是否产生大量开销或错过一些必不可少的;-)

好的,首先我通过命令行创建了一个TwigExtension

php bin/console make:twig-extension AppExtension

然后我将类修改为如下形式:

<?php

namespace App\Twig;

use App\Repository\ArticleRepository;
use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class AppExtension extends AbstractExtension implements ServiceSubscriberInterface
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('article_sidebar', [$this, 'getArticleSidebar'], ['needs_environment' => true, 'is_safe' => ['html']]),
        ];
    }

    public function getArticleSidebar(\Twig_Environment $twig)
    {
        $articleRepository = $this->container->get(ArticleRepository::class);
        $archive = $articleRepository->myAwesomeLogic('omegalul');

        return $twig->render('/article/sidebar.html.twig', [
           'archive' => $archive,
        ]);
    }

    public static function getSubscribedServices()
    {
        return [
            ArticleRepository::class,
        ];
    }
}

为了激活惰性性能,因此当我们使用Twig时,不会每次都实例化我们的存储库和其他Twig_Environment 我们实现ServiceSubscriberInterface并添加getSubscribedServices方法。

因此,仅当我们在模板中实际调用{{ article_sidebar() }}时,实例化我们的Repo和Twig_Environment。

{# example-template article_base.html.twig #}
{% extends 'base.html.twig' %}
{% block body %}
    <div class="row">
        <div class="col-10">
            {% block article_body %}{% endblock %}
        </div>
        <div class="col-2">
            {{ article_sidebar() }}
        </div>
    </div>
{% endblock %}

现在,我可以像这样为文章路线定义模板:

{# example-template /article/show.html.twig #}
{% extends 'article_base.html.twig' %}
{% block article_body %}
    {# display the article here #}
{% endblock %}