如何在 Symfony (Twig) 中包含可重用的小部件?

2023-12-29

所以,我对 Symfony 和 Twig 还很陌生。我想知道如何最好地在模板中包含/创建可重用代码片段。例如,假设您有一个想要在每个页面上显示的侧边栏。

{% extends 'AppBundle::base.html.twig' %}

{% block body %}
    <div id="wrapper">
        <div id="content-container">
            {# Main content... #}
        </div>
        <div id="sidebar">
            {% include 'sidebar.html.twig' %}
        </div>
    </div>
{% endblock %}

在那个侧边栏中有几个小部件,它们都有自己的逻辑。您如何创建/包含这些小部件?

到目前为止,我已经遇到了几种解决方案。

作为控制器

第一个是将小部件嵌入为控制器 https://symfony.com/doc/current/templating/embedding_controllers.html在树枝中。

class WidgetController extends Controller
{
    public function recentArticlesWidgetAction()
    {
        // some logic to generate to required widget data
        // ...

        // Render custom widget template with data
        return $this->render('widgets/recentArticles.html.twig', array('data' => $data)
        );
    }
    public function subscribeButtonWidgetAction()
    {
        // ...

        return $this->render('widgets/subscribeButton.html.twig', array('data' => $data)
    }

    // Many more widgets
    // ...
}

并将其包含在“sidebar.html.twig”中,如下所示

<div id="sidebar">        
    {# Recent Articles widget #}
    {{ render(controller('AppBundle:Widget:recentArticlesWidget' )) }}

    {# Subscribe-Button widget #}
    {{ render(controller('AppBundle:Widget:subscribeButtonWidget' )) }}

    {# and so on #}
</div>

作为一项服务

我还看到有些人将小部件注册为服务(可以直接在 Twig 中使用)。与小部件主类

// src/AppBundle/Service/RecentArticlesWidget.php
namespace AppBundle\Service;

use Symfony\Component\DependencyInjection\ContainerInterface;

class RecentArticlesWidget
{
    protected $container;

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

    public function getRecentArticles()
    {
        // do some logic (use container for doctrine etc.)
    }
}

然后注册为服务,

# src/AppBundle/Resources/config/services.yml
services:
    recentArticlesWidget:
        class:     AppBundle\Service\RecentArticlesWidget
        arguments: ["@service_container"]

传递到控制器中的模板,

namespace AppBundle\Controller;

class SidebarController {

    public function showAction($request) {

        // Get the widget(s) 
        $recentArticlesWidget = $this->get('recentArticlesWidget'); 

        // Pass it (them) along
        return $this->render('sidebar.html.twig', array('recentArticlesWidget' => $recentArticlesWidget));
    }
}

所以它可以像这样在 Twig 中简单地使用

{# sidebar.html.twig #}

{{ recentArticlesWidget.getRecentArticles()|raw }}

或者,您还可以通过将服务添加到 Twig 配置来直接将其添加到 Twig 全局变量。这样,控制器就不需要将其传递到视图中。

#app/config/config.yml
twig:
    globals:
        # twig_var_name: symfony_service
        recentArticlesWidget: "@recentArticlesWidget"

作为树枝扩展

这与使用上面的服务非常相似(请参阅文档 http://symfony.com/doc/current/templating/twig_extension.html)。您创建一个与之前显示的服务几乎相同的树枝扩展类

// src/AppBundle/Twig/RecentArticlesWidgetExtension.php
namespace AppBundle\Twig;

class RecentArticlesWidgetExtension extends \Twig_Extension
{
    protected $container;

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

    public function getFunctions()
    {
        return array( 
            "getRecentArticles" => new Twig_Function_Method($this, "getRecentArticles")
            // register more functions
        );
    }

    public function getRecentArticles()
    {
        // do some logic (use container for doctrine etc.)
    }

    // Some more functions...

    public function getName()
    {
        return 'WidgetExtension';
    }
}

将其注册为带有添加标签的服务

# src/AppBundle/Resources/config/services.yml
services:
    recentArticlesWidget:
        class: AppBundle\Twig\RecentArticlesWidgetExtension
        arguments: [@service_container]
        tags:
            - { name: twig.extension }

并像 Twig 中的全局函数一样使用它

{# sidebar.html.twig #}

{{ getRecentArticles() }}

Thoughts

我注意到的一件事是,使用最后两种方法时,逻辑和视图似乎不再分开。您基本上编写了一个小部件函数,并让该函数输出该小部件的完整 html。这似乎违背了 Symfony 试图强制执行的模块化和模式。

另一方面,为每个小部件调用不同的控制器或控制器操作(使用它们自己的树枝渲染)似乎可能需要比实际需要更多的处理。我不确定它是否真的减慢了速度,但我确实想知道它是否过度。

长话短说,在 Symfony 中是否有使用可重用小部件的最佳实践?我确信其中一些方法也可以混合使用,所以我只是想知道如何最好地解决这个问题。


Twig 扩展和 Twig 宏应该为您指明正确的方向。

使用宏作为视图,使用扩展作为业务逻辑。

在你的 Twig 扩展示例中,顺便说一句,只传递你正在使用的服务而不是整个服务容器可能是个好主意。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Symfony (Twig) 中包含可重用的小部件? 的相关文章

  • Symfony2 和 Doctrine,OneToOne 关系中的 Column 不能为 null

    这是一个实体 编辑 完整文件内容 Eve MoonBundle Entity MoonMaterial php namespace Eve MoonBundle Entity use Doctrine ORM Mapping as ORM
  • symfony 2.0足够稳定可以使用吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我怀疑是否交响乐2 0够稳定可以使用吗 因为我从来没有用过Symfony before 看起来交响乐2比以前的版本好得多 我不想在几个月后重新学
  • Symfony2 / 路由 / 使用参数作为控制器或操作名称

    是否可以使用给定参数路由到控制器 操作 例如 my custom route pattern controller action defaults controller AcmeDemoBundle controller action 我希
  • Doctrine QueryBuilder 重用部件

    我想计算所有符合我的条件的字段 并使用学说查询生成器逐页获取它们 我生成的查询取决于我的过滤器字段 第一部分是计算记录 以便我可以计算页数 qb em gt createQueryBuilder qb gt select COUNT m i
  • Symfony 2 中的可选嵌入形式

    我的系统中有两个实体 Person and Phone如下面的代码 class Person ORM Id ORM Column type integer ORM GeneratedValue strategy AUTO private i
  • 手动渲染 Twig 字符串时禁用 HTML 转义

    我有以下代码将字符串呈现为 HTML 输出 如何阻止它转义 HTML 文本 template who bar params array who gt Foo s twig new Twig Environment new Twig Load
  • 获取 iTunes 中当前播放的歌曲

    我想获取 iTunes 当前正在播放的歌曲的名称 我应该参考什么API 我想将其用于仪表板小部件或 Java Python 应用程序 具体取决于它更容易使用 你有一些参考资料给我吗 提前致谢 马里奥 这是一个 AppleScript 它将告
  • 在 laravel 中创建项目时,output.php 中 Symfony 解析错误

    安装了 Laravel 5 6 还安装了 PHP 7 0 当我尝试时 laravel new sample project 它创建了所需的文件和依赖项 但出现以下错误 PHP Parse error syntax error unexpec
  • FOS/用户捆绑包 ProxyManager\配置错误

    安装friendsofsymfony user bundle后我收到此错误 FatalThrowableError in Configuration php line 124 Type error Return value of Proxy
  • 在 Visual Studio 2017 中使用 .wid 文件

    我已经使用 Visual Studio 2017 Professional 创建了一个安装项目 vdproj file 我想使用本页中建议的密码对话框 https www codeproject com Tips 659367 Passwo
  • 模式匹配 Tkinter 子部件 (winfo_children) 以确定类型

    我正在尝试自动清除所有Entry父小部件中的小部件 import Tkinter import re root Tkinter Tk E1 Tkinter Entry root E1 pack E2 Tkinter Entry root E
  • 通过嵌入式 Google Sheet 上的按钮激活脚本

    我正在尝试嵌入一个 Google 电子表格 其中包含一个我希望用户能够激活的脚本 我不希望他们能够编辑页面上的任何内容 我想我可以这样做 共享工作表并设置编辑权限 限制在我想要共享的一张纸上进行编辑 图像位于单元格上方 所以我认为这会阻止人
  • twig json_encode 空 json

    我正在从 API 接收元素列表 所有元素的格式都很好 当我使用树枝转储其中一个时 我得到以下信息 Leg 2695 id null reservation null airportStart AIX LES MILLES airplaneT
  • Symfony Doctrine 数据类型仅适用于 findBy 不适用于 querybuilder

    我有自定义数据类型 它在使用 FindBy 时按预期工作 但在使用查询生成器时却不然 很抱歉这篇文章很长 但我认为更多信息应该有所帮助 这与这个未回答的问题相同 学说 2 自定义类型 https stackoverflow com ques
  • 在 symfony 2.1 中安装并运行 LiipImagineBundle

    以下是我遵循的步骤 在我的composer json中添加了以下内容 require imagine Imagine gt 0 2 8 liip imagine bundle dev 在命令行中运行以下命令 composer update
  • Symfony 2 FOSUserBundle 与产品表的关系

    如果之前有人问过这个问题 我提前道歉 我已成功设置 FOSUserBundle 我正在尝试设置 http symfony com doc current book doctrine html http symfony com doc cur
  • 在 Symfony2 中使用 assetic 加载一个 js 文件

    我是 Symfony 2 的新手 之前我经常使用 Codeigniter 现在我正在探索 assetic 我无法理解如何将单个文件添加到已经加载的 JS 文件堆栈中 我有一个主页树枝文件 其中包含以下内容 javascripts BlogB
  • 隐藏嵌入的 pdf 周围的工具栏?

    虽然我认为答案可能在这另一个问题 https stackoverflow com questions 770949 how to disable the default toolbar of pdf page关于pdf规范的回答 是否可以不
  • Symfony2 功能测试会话持久性

    我正在尝试在 Symfony 中进行一些功能测试 但目前我的会话遇到了问题 我执行了一段代码 它似乎有效 但容器的会话中没有存储任何内容 我有一个表格 您可以在其中设置数据 当您提交它时 它会检查值并将其存储在会话中 然后它重定向到另一个页
  • 在 Symfony 序列化中更改序列化属性名称

    我正在使用 Symfony 序列化器 效果很好 use Symfony Component Serializer Annotation Groups Groups default notification public function g

随机推荐