2

Symfony2 アプリケーションでは、再利用可能なブロックを render_esi でレンダリングします。このようなテンプレートがあります:

{% 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 %}

もちろん、製品の詳細ページでも render_esi を使用しています。

4

1 に答える 1

2

さまざまなタイプのブロックを区別したいと思います。

  • 同じコントローラーの他のアクションをレンダリングするブロック。
  • アプリケーションの他の部分で使用できるブロック。

違いはなんですか?

親テンプレートと同じコントローラーの他のアクションのみをレンダリングするブロックは、ほとんどの場合、1 つのページをモジュール化し、パーツをキャッシュ可能にするために存在します。このブロックは、アプリケーション全体で 1 回だけ使用されます。

評価の星やコメントなどのパーツをレンダリングするブロックは、特定の機能を提供する一種の独立したウィジェットです。現在のコントローラーは、このウィジェットについて何も知りません。この種のブロックは、ほとんどの場合、アプリケーションで複数回使用されます。

それはソフトウェア設計にとって何を意味するのでしょうか?

これは、コメントと評価の仕組みを将来的に変更する可能性があることを意味します。サードパーティのサービスに機能を委託しており、この場所に何らかの JavaScript を含めるだけでよいため、今後 ESI によってレンダリングされなくなる可能性はありますか? それとも、それらを直接レンダリングしますか?

これは、ウィジェットを含むパーツではなく、ウィジェットによって決定されなければならないものです。

では、デザインを改善するにはどうすればよいでしょうか?

ESI を使用し続けることもできますが (ユースケースにとって意味があるため)、モジュールを Twig ファイルに含める方法を変更する必要があります。このロジックをテンプレートから AcmeDemoCommunityBundle の別の Twig 拡張機能に移動する必要があります。

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 }

テンプレートは次のようになります。

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

この設計により、アプリケーションで評価の星を簡単に使用できますが、評価が使用されるテンプレートに触れることなく、将来評価がどのように機能するかを実装を変更する柔軟性もあります。

于 2014-05-12T11:22:35.240 に答える