0

Twig 拡張機能を作成し、これを使用したい:

{{ new_func(route-name) }}

以下と同じことを行うには:

{{ render_esi(url(route-name)) }}

...しかし、いくつかの調整を加えて

ほぼ完了ですが、変更する必要があるのはこの行ですが、このコード (Twig の外部) から ESI を呼び出す方法がわかりません。

return $environment->render($route);   /// needs to receive route and render an ESI

-

namespace Acme\Bundle\MyBundle\Twig;

class NewTwigFunction extends \Twig_Extension
{

    private $request;

    public function __construct($container)
    {
        $this->request = $container->get('request');
    }

    public function getFunctions() {

        return array(
            'new_func' => new \Twig_Function_Method($this, 'newFunction', array('needs_environment' => true) )
        );

    }

    public function newFunction(\Twig_Environment $environment, $route) {

        $r = $this->request;

        return $environment->render($route);

    }

    public function getName() {

        return "new_func";

    }

 }
4

1 に答える 1

11

なぜこれが必要なのかはわかりませんが、抽象的な質問の例としては素晴らしいと思います:

Symfony2 のコア機能を追跡して拡張するにはどうすればよいですか?

機能を見つける

これが実行された場所を見つけるのに苦労しているようですrender_esiので、それに取り組みましょう!

これは標準の Twig 機能のようには見えないため、作成しているものと同じように、拡張機能である必要があります。

これは Symfony2 コア ファイルのどこかにあるはずなので、vendor/symfony/srcフォルダーを調べ始めます。Twig の拡張機能を扱っていることは既にわかっているので、Componentフォルダーは問題外です (Twig は Symfony2 のコア コンポーネントとは別のライブラリであるため)。

Bridgeそのため、 とに絞り込みましたBundle。それらの中を見るとBundle/TwigBundle、 またはが表示されますBridge/Twig。また、Symfony2 の開発者が厳密なコード/アーキテクチャ スタイルに従っていることもわかっているため、どのフォルダーを探すべきかが正確にわかります - Extension. あとは、両方をチェックするだけです。

簡単に言うと、探しているものを で見つけます。vendor/symfony/src/Symfony/Bridge/Twig/Extension/HttpKernelExtensionここにrender_*関数が表示されます。ジャックポット!

機能の拡張

何かを変更する前に、まず既存のものをエミュレートする必要があるため、次のようなものを作成します。

use Symfony\Component\HttpKernel\Fragment\FragmentHandler;

class NewTwigFunction extends \Twig_Extension
{
    private $handler;

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

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

    public function newFunction($uri, $options = array()) 
    {
        return $this->handler->render($uri, 'esi', $options);
    }

    public function getName() 
    {
        return "new_func";
    }

 }

今あなたが電話するとき

{{ new_func(url(route-name)) }}

と同じ結果が表示されるはずです

{{ render_esi(url(route-name)) }}

urlしかし、まだその部分を取り除く必要があります。パイのように簡単routerに、拡張機能にサービスを追加するだけです! 拡張機能は次のようになります。

use Symfony\Component\Routing\Router;
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;

class NewTwigFunction extends \Twig_Extension
{
    private $handler;
    private $router;

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

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

    public function newFunction($routeName, $options = array()) 
    {
        $uri = $this->router->generate($routeName);

        return $this->handler->render($uri, 'esi', $options);
    }

    public function getName() 
    {
        return "new_func";
    }

 }

期待どおりに{{ new_func(route-name) }}動作するはずです。

間にフック

私が理解した方法では、 とほぼ同じ機能が必要ですrender_esiが、出力がわずかに変更されています。つまり、 と の間のどこかにフックする必要がreturnあり$this->handler->render($uri, $strategy, $options);ます。

うさぎの穴をどれだけ深く掘り下げる必要があるかは、変更によって異なります。

たとえば、Response実際のオブジェクトに変更する前にオブジェクトを変更したい場合html stringは、最初にオブジェクトが変更された場所を見つける必要があります。良い賭けは、調べることFragmentHandlerです:

protected function deliver(Response $response)
{
    if (!$response->isSuccessful()) {
        throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->request->getUri(), $response->getStatusCode()));
    }

    if (!$response instanceof StreamedResponse) {
        return $response->getContent();
    }

    $response->sendContent();
}

とった!あとは、実装を拡張FragmentHandler::deliver()して twig エクステンションに渡すだけです。

構成の追跡

Symfony2 のコア コードは、日常生活で書くものとそれほど変わらず、独自の規則に従っていることを理解する必要があります。

たとえば、通常 Symfony2 で Twig 拡張機能を作成する場合、それをサービスとして構成する必要がありますよね? まあ、Symfony2 コア拡張機能は同じ方法で構成されます。構成ファイルの場所を見つけるだけです。

機能を拡張するのロジックに従って、Component. Bridge実際にはデザインパターンの名前です-サービス構成を配置する場所ではありません:)

これでBundle、必要な情報がすべて見つかります。vendor/symfony/src/Bundle/TwigBundle/Resources/config/twig.xml

次に、オリジナルのHttpKernelExtension構成方法を調べて、そのリードに従います。

    <service id="twig.extension.httpkernel" class="%twig.extension.httpkernel.class%" public="false">
        <argument type="service" id="fragment.handler" />
    </service>

より一般的に使用される.yml形式に変換すると、拡張機能の構成は次のようになります。

new_func:
    class: Acme\Bundle\MyBundle\Twig\NewTwigFunction
    arguments:
        - "@fragment.handler"
        # Uncomment when implementing code from 2nd example
        # - "@router"
    tags:
        - { name: twig.extension }
    public: false
于 2013-06-06T08:34:10.393 に答える