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