我想创建一个Twig扩展并使用它:
{{ new_func(route-name) }}
Run Code Online (Sandbox Code Playgroud)
做同样的事情:
{{ render_esi(url(route-name)) }}
Run Code Online (Sandbox Code Playgroud)
......但有一些调整
它已接近完成,但这条线需要更改,但我无法看到如何从此代码(在Twig之外)调用ESI:
return $environment->render($route); /// needs to receive route and render an ESI
Run Code Online (Sandbox Code Playgroud)
-
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";
}
}
Run Code Online (Sandbox Code Playgroud)
Ino*_*ryy 11
我不确定我会说你为什么需要这个,但我认为这是一个抽象问题的例子:
似乎你无法找到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";
}
}
Run Code Online (Sandbox Code Playgroud)
现在你打电话的时候
{{ 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";
}
}
Run Code Online (Sandbox Code Playgroud)
并{{ 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();
}
Run Code Online (Sandbox Code Playgroud)
得到它了!现在你只需要将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>
Run Code Online (Sandbox Code Playgroud)
将其转换为更常用的.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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1406 次 |
| 最近记录: |