扩展 Twig 的 AppVariable
Extending Twig's AppVariable
我继承了一个使用 Symfony 2 的网站。
在我 运行 composer 升级软件包之前,该站点运行良好。它将 Symfony 2.6 升级到 2.7.1,将 Twig 1.18 升级到 1.18.2。
我现在收到以下错误:
Method "site" for object "Symfony\Bridge\Twig\AppVariable" does not exist in @Page/Page/homepage.html.twig at line 21
有问题的 twig 文件有这样的调用:
{{ app.site.name }}
现在显然 site
不是 AppVariable
类型的成员。我无法弄清楚最初的开发人员如何设法通过新成员扩展 Twig 的 app
全局。我真的不知道去哪里看。我不太擅长 Symfony。
老开发人员所做的可能是覆盖 app
变量。在 Symfony @2.7 之前,class 被称为 GlobalVariables
并且存在于以下命名空间中 - Symfony\Bundle\FrameworkBundle\Templating
。从 @2.7 开始,它被称为 AppVariable
并且它存在于这个命名空间中 - Symfony\Bridge\Twig
。幕后做了什么?
包含全局变量的 class 使用 Twig 的方法 addGlobal
简单地添加为 twig 全局变量,并且对于 app
的值,它们注入整个 class 作为已经定义的服务。 GlobalVariables
或 AppVariables
接受服务容器作为参数,并默认定义了 5 个可以在我们的模板中使用的方法。我将向您展示一种扩展该 class 的简单方法,以便您可以使用它进行调查。
创建我们将定义为服务的简单 class:
<?php
namespace AppBundle\Service;
use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables,
Symfony\Component\DependencyInjection\ContainerInterface;
class SuperGlobalsExtended extends GlobalVariables {
/**
* @var ContainerInterface
**/
protected $container = null;
public function __construct(ContainerInterface $container) {
$this->container = $container;
parent::__construct($container);
}
}
然后注册它:
services:
app.super_globals_extended:
class: AppBundle\Service\SuperGlobalsExtended
arguments:
- @service_container
最后但同样重要的是,覆盖 twig 的 app
变量:
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
app: @app.super_globals_extended
现在您可以在扩展 class 中定义自己的方法,也可以访问此处已有的以前的方法。
对于 symfony @2.7 是一样的,只是 class 名称不同。这里我扩展了 GlobalVariables
,但是对于 @2.7 你必须扩展 AppVariable
.
@2.7 的服务定义位于 TwigBundle Resources 文件夹中。
<service id="twig" class="%twig.class%">
<argument type="service" id="twig.loader" />
<argument /> <!-- Twig options -->
<call method="addGlobal">
<argument>app</argument>
<argument type="service" id="twig.app_variable" />
</call>
<configurator service="twig.configurator.environment" method="configure" />
</service>
希望这对您有所帮助。
参考作为起点。
看起来像 sf3,AppVariable
class 不再需要容器(并且没有 parent::__construct
)但是有趣的变量被直接设置。
因此,我在 services.yml
中使用此设置设置了我的 class MyAppExtension extends AppVariable
:
extended_twig_app:
class: AppBundle\Twig\MyAppExtension
public: false
calls:
- [setEnvironment, ["%kernel.environment%"]]
- [setDebug, ["%kernel.debug%"]]
- [setTokenStorage, ['@security.token_storage']]
- [setRequestStack, ['@request_stack']]
这基本上是 xml->yml 对 Twig Bundle 中相应代码的转换:
https://github.com/symfony/twig-bundle/blob/master/Resources/config/twig.xml
<service id="twig.app_variable" class="Symfony\Bridge\Twig\AppVariable" public="false">
<call method="setEnvironment"><argument>%kernel.environment%</argument></call>
<call method="setDebug"><argument>%kernel.debug%</argument></call>
<call method="setTokenStorage"><argument type="service" id="security.token_storage" on-invalid="ignore" /></call>
<call method="setRequestStack"><argument type="service" id="request_stack" on-invalid="ignore" /></call>
</service>
我继承了一个使用 Symfony 2 的网站。
在我 运行 composer 升级软件包之前,该站点运行良好。它将 Symfony 2.6 升级到 2.7.1,将 Twig 1.18 升级到 1.18.2。
我现在收到以下错误:
Method "site" for object "Symfony\Bridge\Twig\AppVariable" does not exist in @Page/Page/homepage.html.twig at line 21
有问题的 twig 文件有这样的调用:
{{ app.site.name }}
现在显然 site
不是 AppVariable
类型的成员。我无法弄清楚最初的开发人员如何设法通过新成员扩展 Twig 的 app
全局。我真的不知道去哪里看。我不太擅长 Symfony。
老开发人员所做的可能是覆盖 app
变量。在 Symfony @2.7 之前,class 被称为 GlobalVariables
并且存在于以下命名空间中 - Symfony\Bundle\FrameworkBundle\Templating
。从 @2.7 开始,它被称为 AppVariable
并且它存在于这个命名空间中 - Symfony\Bridge\Twig
。幕后做了什么?
包含全局变量的 class 使用 Twig 的方法 addGlobal
简单地添加为 twig 全局变量,并且对于 app
的值,它们注入整个 class 作为已经定义的服务。 GlobalVariables
或 AppVariables
接受服务容器作为参数,并默认定义了 5 个可以在我们的模板中使用的方法。我将向您展示一种扩展该 class 的简单方法,以便您可以使用它进行调查。
创建我们将定义为服务的简单 class:
<?php
namespace AppBundle\Service;
use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables,
Symfony\Component\DependencyInjection\ContainerInterface;
class SuperGlobalsExtended extends GlobalVariables {
/**
* @var ContainerInterface
**/
protected $container = null;
public function __construct(ContainerInterface $container) {
$this->container = $container;
parent::__construct($container);
}
}
然后注册它:
services:
app.super_globals_extended:
class: AppBundle\Service\SuperGlobalsExtended
arguments:
- @service_container
最后但同样重要的是,覆盖 twig 的 app
变量:
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
app: @app.super_globals_extended
现在您可以在扩展 class 中定义自己的方法,也可以访问此处已有的以前的方法。
对于 symfony @2.7 是一样的,只是 class 名称不同。这里我扩展了 GlobalVariables
,但是对于 @2.7 你必须扩展 AppVariable
.
@2.7 的服务定义位于 TwigBundle Resources 文件夹中。
<service id="twig" class="%twig.class%">
<argument type="service" id="twig.loader" />
<argument /> <!-- Twig options -->
<call method="addGlobal">
<argument>app</argument>
<argument type="service" id="twig.app_variable" />
</call>
<configurator service="twig.configurator.environment" method="configure" />
</service>
希望这对您有所帮助。
参考
看起来像 sf3,AppVariable
class 不再需要容器(并且没有 parent::__construct
)但是有趣的变量被直接设置。
因此,我在 services.yml
中使用此设置设置了我的 class MyAppExtension extends AppVariable
:
extended_twig_app:
class: AppBundle\Twig\MyAppExtension
public: false
calls:
- [setEnvironment, ["%kernel.environment%"]]
- [setDebug, ["%kernel.debug%"]]
- [setTokenStorage, ['@security.token_storage']]
- [setRequestStack, ['@request_stack']]
这基本上是 xml->yml 对 Twig Bundle 中相应代码的转换: https://github.com/symfony/twig-bundle/blob/master/Resources/config/twig.xml
<service id="twig.app_variable" class="Symfony\Bridge\Twig\AppVariable" public="false">
<call method="setEnvironment"><argument>%kernel.environment%</argument></call>
<call method="setDebug"><argument>%kernel.debug%</argument></call>
<call method="setTokenStorage"><argument type="service" id="security.token_storage" on-invalid="ignore" /></call>
<call method="setRequestStack"><argument type="service" id="request_stack" on-invalid="ignore" /></call>
</service>