当我尝试在Symfony2项目中实现自定义Twig扩展时,出现以下错误:
无法注册扩展程序“AppBundle \ Twig \ Extension \ FileExtension” 因为它已经注册了。
在我的app / config / services.yml中,我有以下内容:
parameters:
app.file.twig.extension.class: AppBundle\Twig\Extension\FileExtension
services:
app.twig.file_extension:
class: '%app.file.twig.extension.class%'
tags:
- { name: 'twig.extension' }
在AppBundle / Twig / Extensions / FileExtension中,我有:
<?php
namespace AppBundle\Twig\Extension;
class FileExtension extends \Twig_Extension
{
/**
* Return the functions registered as twig extensions
*
* @return array
*/
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('file_exists', array($this, 'file_exists')),
);
}
public function getName()
{
return 'app_file';
}
}
?>
我试图清除缓存,但没有工作。有人想过为什么Twig会渲染两次吗?
答案 0 :(得分:3)
正如@Cerad所述,从Symfony 3.3 开始,自动加载了枝条扩展,无需在默认services.yml
中定义任何内容。
如果您使用默认的services.yml配置,那么您就完成了! Symfony会自动了解您的新服务并添加标签。
答案 1 :(得分:1)
这个问题仍然没有实际答案,恕我直言。
首先,Twig不会渲染两次,但会尝试注册您的扩展两次。但是Twig只允许将一个特定的类注册为扩展名。
那么,为什么Twig尝试注册两次?
因为现在有两个服务具有相同的类和各自的标签,它们告诉Twig这些服务是twig的扩展。
但是为什么有两项服务?
好吧,有一个手动定义的:app.twig.file_extension
,另一个由默认配置services.yml
中的配置自动定义:
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
Cerad的评论指向autoconfigure
文档,我认为这具有误导性。使用autoconfigure
,Symfony将自动将树枝标签应用于第二个(自动配置的)服务。
是的,您可以通过关闭autoconfigure
来解决此问题。然后,您有两项服务,但只有手动配置的一项才具有需要识别为枝条扩展的标签。
Ziad Akiki的答案引用了文档,指出您不需要进行进一步的配置。但是仅仅因为您不需要 并不意味着您不能,我什至可以想象有效的用例。这就是为什么我认为这不是一个实际的答案。实际上,您可以 ,只需在服务条目的类名后命名即可:
services:
AppBundle/Twig/Extensions/FileExtension:
tags:
- { name: 'twig.extension' }
答案 2 :(得分:0)
在symfony 4中,如果您具有自动装配功能,则可以忘记配置services.yaml,您的代码在服务中看起来相同,只是更改文件夹的路径。
namespace App\Util;
use Symfony\Component\HttpKernel\KernelInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class RemoteFileExtension extends AbstractExtension
{
private $kernel;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
public function getFunctions()
{
return array(
new TwigFunction('remote_file', array($this, 'remoteFile')),
);
}
public function remoteFile($url)
{
$contents = file_get_contents($url);
$file = $this->kernel->getRootDir() . "/../templates/temp/" . sha1($contents) . '.html.twig';
if (!is_file($file))
{
file_put_contents($file, $contents);
}
return '/temp/' . basename($file);
}
public function getName()
{
return 'remote_file';
}
}
答案 3 :(得分:0)
我在Symfony 3.4项目中遇到了相同的错误。
这是将自定义TechnicianService依赖项注入到树枝扩展中,导致在我的情况下。经过大量的反复试验,解决方案是将特定功能从TechnicianService移至TechnicianRepository中的某个功能,然后将EntityManagerInterface注入到twig扩展中,从中我可以再次访问已移动的功能。
所以一开始我有
class FindTechnicianByUrlExtension extends \Twig_Extension
{
private $technicianService;
/**
* @param TechnicianService $technicianService
*/
public function __construct(TechnicianService $technicianService)
{
$this->technicianService = $technicianService;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('findTechnicianByUrl', function ($url) {
return $this->technicianService->findTechnicianByUrl($url);
})
];
}
}
必须更改为此:
class FindTechnicianByUrlExtension extends \Twig_Extension
{
private $em;
/**
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('findTechnicianByUrl', function ($url) {
return $this->em->getRepository(Technician::class)->findTechnicianByUrl($url);
})
];
}
}
这是一个遗留项目。一些较旧的服务没有自动接线,可能配置不同。...我的新Twig扩展程序使用自动接线。不知道是什么原因导致了问题,但我确实已解决。如果有人通过阅读我的解决方案知道确切的原因,请告诉我。