能否以及如何重写一个在依赖关系中定义的Twig函数?
ThirdPartyCode\HelloExtension
定义 hello($string name)
Twig函数,返回 Hello, {$name}
.
在我的代码里 App\MyHelloExtension extends HelloExtension
我想覆盖 hello($string name)
函数返回 Bye, {$name}
.
然而,当我用相同的名字定义函数时,第三方的函数被使用,而我的函数从未被调用。如果我给它取不同的名字,如 hello2
它就能正常工作。
你可以完全替换现有的函数,确保它不会被加载。你可以通过编写一个在构建服务容器的最后一步工作的CompilerPass来实现。这个CompilerPass会通过服务的idclass名称、是否注册来查找服务,然后从容器中删除它。这将完全删除现有的扩展,你可以在它的位置加载你的扩展。
请看 https:/symfony.comdoccurrentservice_containercompiler_passes.html。
或者你可能想使用现有扩展的逻辑,然后在它的基础上构建。对于这种服务,装饰可能是一个很好的选择,因为装饰后的服务会取代原来的服务,同时在必要时仍然可以访问底层装饰的服务。
services:
App\MyHelloExtension:
decorates: ThirdpartyCode\Extension
arguments:
- '@App\MyHelloExtension.inner' # this passes the decorated service, i.e. the original extension as an argument, see code snippet below
这将确保每当有东西检索服务时 ThirdpartyCode\Extension
的容器中,他们会得到你的扩展。意味着你的扩展将被加载到它的位置。当你的代码扩展了现有的扩展(如在你的代码片段中所看到的)或使用了像这样的合成时,这就特别好用。
class MyHelloExtension extends TwigExtension
{
private $originalExtension;
public function __construct(HelloExtension $helloExtension)
{
$this->originalExtension = $helloExtension;
}
// ...
public function hello($name)
{
// Your method can still utilize the underlying original method if necessary.
return $this->originalExtension->hello() . ' ' . $name;
}
}
参见: https:/symfony.comdoccurrentservice_containerservice_decoration.html)。
当你装修服务的时候,你要注意只有一个分机是在Twig注册的。你可能应该确保 autoconfigure: false
设置在你自己的扩展上,并且你没有把它标记为 twig.extension
.