Twig:渲染与包含

发布于 2024-12-31 22:59:31 字数 2773 浏览 2 评论 0原文

我正在创建一个在线商店。 如果我使用树枝函数“渲染”而不是“包含”,我会遇到性能问题。

这是显示产品目录的代码:

目录控制器:

<?php
// src/Acme/StoreBundle/Controller/Product/Catalog.php

namespace Acme\StoreBundle\Controller\Product;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class CatalogController extends Controller
{
    /**
     * @Template()
     */
    public function productAction(\Acme\StoreBundle\Entity\Product\Category $category)
    {
        $qb = $this->getDoctrine()
            ->getRepository('StoreBundle:Product')
            ->createQueryBuilder('product')
            ->select('partial product.{id, token, name}')
            ->innerJoin('product.categoryRelation', 'categoryRelation')
            ->where('categoryRelation.category = :category_id');

        $qb->setParameters(array(
            'category_id'  => $category->getId(),
        ));

        $products = $qb->getQuery()
            ->getResult();

        return $this->render('StoreBundle:Product\Catalog:product.html.twig', array(
            'category' => $category,
            'products' => $products,
        ));
    }
}

... 目录控制器的模板:

{# src/Acme/StoreBundle/Resources/views/Product/Catalog/product.html.twig #}
{% extends 'AcmeDemoBundle::layout.html.twig' %}

{% block content %}
    <h1>{{ category.name }}</h1>

    <ul>
    {% for product in products %}
        <li>
            {#% render "StoreBundle:Product:show" with { product: product } %#}
            {% include "StoreBundle:Product:show.html.twig" with { product: product } %}
        </li>
    {% endfor %}
    </ul>

{% endblock %}

... 产品控制器:

<?php
// src/Acme/StoreBundle/Controller/Product.php

namespace Acme\Enter\StoreBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

use Enter\StoreBundle\Entity\Product;

class ProductController extends Controller
{
    /**
     * @Template()
     */
    public function showAction(Product $product)
    {
        return array('product' => $product);
    }
}

... 产品控制器的简单(但将来会更复杂)模板:

{# src/Acme/StoreBundle/Resources/views/Product/show.html.twig #}
{{ product.name }}

所以如果我使用:

{% include "StoreBundle:Product:show.html.twig" with { product: product } %}

.. .一切正常:147ms和4608Kb内存。

但是当我需要一个控制器来显示产品时:

{% render "StoreBundle:Product:show" with { product: product } %#}

...我的脚本消耗了太多的时间和内存:3639ms和17664Kb内存!

如何通过使用控制器来提高速度并减少内存消耗?

I am creating an online store.
I have a performance problem if I use the twig function "render" instead of "include".

Here is the code that displays a product catalog:

catalog controller:

<?php
// src/Acme/StoreBundle/Controller/Product/Catalog.php

namespace Acme\StoreBundle\Controller\Product;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class CatalogController extends Controller
{
    /**
     * @Template()
     */
    public function productAction(\Acme\StoreBundle\Entity\Product\Category $category)
    {
        $qb = $this->getDoctrine()
            ->getRepository('StoreBundle:Product')
            ->createQueryBuilder('product')
            ->select('partial product.{id, token, name}')
            ->innerJoin('product.categoryRelation', 'categoryRelation')
            ->where('categoryRelation.category = :category_id');

        $qb->setParameters(array(
            'category_id'  => $category->getId(),
        ));

        $products = $qb->getQuery()
            ->getResult();

        return $this->render('StoreBundle:Product\Catalog:product.html.twig', array(
            'category' => $category,
            'products' => $products,
        ));
    }
}

... template for catalog controller:

{# src/Acme/StoreBundle/Resources/views/Product/Catalog/product.html.twig #}
{% extends 'AcmeDemoBundle::layout.html.twig' %}

{% block content %}
    <h1>{{ category.name }}</h1>

    <ul>
    {% for product in products %}
        <li>
            {#% render "StoreBundle:Product:show" with { product: product } %#}
            {% include "StoreBundle:Product:show.html.twig" with { product: product } %}
        </li>
    {% endfor %}
    </ul>

{% endblock %}

... product controller:

<?php
// src/Acme/StoreBundle/Controller/Product.php

namespace Acme\Enter\StoreBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

use Enter\StoreBundle\Entity\Product;

class ProductController extends Controller
{
    /**
     * @Template()
     */
    public function showAction(Product $product)
    {
        return array('product' => $product);
    }
}

... simple (but more complex in future) template for product controller:

{# src/Acme/StoreBundle/Resources/views/Product/show.html.twig #}
{{ product.name }}

So if I use:

{% include "StoreBundle:Product:show.html.twig" with { product: product } %}

...all ok: 147ms and 4608Kb memory.

But when I need a controller to display the product:

{% render "StoreBundle:Product:show" with { product: product } %#}

...my script consumes too much time and memory: 3639ms and 17664Kb memory!

How to increase speed and reduce memory consumption by using the controller?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云仙小弟 2025-01-07 22:59:31

每个渲染调用都会产生一个新请求,并产生您所描述的性能下降问题。我认为除了使用 esi 缓存之外,您对此无能为力,以便可以缓存来自渲染调用的单个片段。否则,您可以尝试修改逻辑以减少渲染调用的使用。

Each render call spawns a new request, with the performance degradation issue that you are describing. I don't think there is much you can do about that but using esi caching, so that single fragments coming from render calls can be cached. Otherwise you could try to revise your logic to reduce the usage of render calls.

软糯酥胸 2025-01-07 22:59:31

如果我错了,请纠正我,但基本思想是包括基本上“复制粘贴”其内容而不是命令。

而渲染命令必须首先创建控制器,初始化它,运行相应的函数等。那么谁知道这个控制器或父级的类、构造函数等内部隐藏着什么重炮呢?

还要记住,甚至包含的模板也会被渲染。因此,当从树枝渲染时,您甚至可能会得到递归或类似的东西。就我个人而言,我尝试避免渲染控制器返回之外的任何内容。

另外,正如 Louis-Philippe Huberdeau 在评论中提到的,由于选项和日志记录不同,开发环境可能与生产模式有很大不同。

至于建议 - 尝试避免将逻辑放入模板中,或者尝试使用模板中经常使用的静态对象来重用它们,而不是一遍又一遍地创建新对象。并仅从控制器渲染内容

Correct me if I am wrong, but the basic idea is that include basically "copy-pastes" its content instead of the command.

Whereas render command must create the controller first, initialize it, run the corresponding function etc. So who knows what heavy artillery is hidden inside this controller's or parent's classes, constructors and so on?

Also remember, that even included templates are rendered. So you even might get recursions or something similar when rendering from twig. Personally I try avoiding rendering anything outside of controller's return.

Plus as mentioned by Louis-Philippe Huberdeau in comments, dev environment can drastically differ from prod mode because of different options and logging.

As for advices - try avoiding putting logic in your templates, or try using static objects that are often used in templates to reuse them instead of creating new ones over and over. And render stuff from controllers only

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文