Is it good practice to put Edge Side Includes into my templates?

有些话、适合烂在心里 提交于 2019-12-11 04:37:00

问题


In our Symfony2 Application we render reusable blocks with render_esi. We have this kind of templates:

{% for products as product %}
<div class="product">
    <h4>{{ product.name }}</h4>
    <div class="ratings">
    {{ render_esi(controller('AcmeDemoCommunityBundle:Rating:ratingStars', {
        objectType: 'product',
        objectId: product.id,
        readOnly: true
    })) }}
    </div>
</div>
{% endfor %}

And of cause we use the render_esi also in the detail page of the product.


回答1:


I would like to differentiate different types of blocks:

  • Blocks that renders other actions of the same controller.
  • Blocks that could be used across other parts of the application.

What is the difference?

Blocks that only renders other actions of the same controller as the parent template are most of the times there to modularize one page and make parts cacheable. This blocks are only used one times in the whole application.

Blocks that renders parts like rating stars or comments are kind of independent widgets that provide an specific functionality. The current controller dose not know anything about this widgets. This kind of blocks are mostly used multiple times in an application.

What does that mean for the software design?

It means that we may want to change the way comments and ratings work in the future. May the not get rendered by an ESI anymore in the future because we have outsourced the functionality to an third-party service and only need to include some kind of JavaScript in this place? Or we render them directly?

This is something that has to be decided by the widget and not by the part that include the widget.

So what could I do to improve my design?

You could keep using ESI (because it makes sense for your usecase), but you should change the way of how the modules are included in the Twig files. You should move the logic for this out of the template into an separate Twig Extension in the AcmeDemoCommunityBundle.

namespace Acme\DemoCommunityBundle\Twig;

use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Acme\DemoCommunityBundle\Rating\RateableInterface;

class CommunityExtension extends \Twig_Extension
{
    /**
     * @var string
     */
    const RATING_ACTION = 'AcmeDemoCommunityBundle:Rating:ratingStars';

    /**
     * @var FragmentHandler
     */
    protected $handler;

    public function __construct(FragmentHandler $handler)
    {
        $this->handler = $handler;
    }

    public function getFunctions()
    {
        return array(
            'community_rating' => new \Twig_Function_Method($this, 'communityRating', array('is_safe' => array('html'))),
        );
    }

    public function communityRating(RateableInterface $object, $readOnly = false)
    {
        return $this->handler->render(new ControllerReference(self::RATING_ACTION, array(
            'objectType' => $object->getRatingType(),
            'objectId' => $object->getId(),
            'readOnly' => $readOnly
        )), 'esi', $options);
    }

    public function getName()
    {
        return 'community';
    }
}
services:
    acme_community.twig.community:
        class:     Acme\DemoCommunityBundle\Twig\CommunityExtension
        arguments: [ @fragment.handler ]
        tags:
            - { name: twig.extension }

Now your template should look like this:

{% for products as product %}
<div class="product">
    <h4>{{ product.name }}</h4>
    <div class="ratings">
    {{ community_rating(product, true) }}
    </div>
</div>
{% endfor %}

With this design it is easy to use the rating stars in our application, but we also have the flexibility to change the implementation how ratings work in the future without touching the templates where ratings are used.



来源:https://stackoverflow.com/questions/23607642/is-it-good-practice-to-put-edge-side-includes-into-my-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!