Symfony - 无法注册扩展名“AppBundle \ Twig \ Extension \ FileExtension”,因为它已经注册

时间:2017-09-03 17:47:24

标签: symfony twig twig-extension

当我尝试在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会渲染两次吗?

4 个答案:

答案 0 :(得分:3)

正如@Cerad所述,从Symfony 3.3 开始,自动加载了枝条扩展,无需在默认services.yml中定义任何内容。

根据official documentation

  

如果您使用默认的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扩展程序使用自动接线。不知道是什么原因导致了问题,但我确实已解决。如果有人通过阅读我的解决方案知道确切的原因,请告诉我。