PHP / Symfony:为什么TwigExtension注入的服务实例与控制器不同?

时间:2019-02-05 08:24:21

标签: php symfony twig twig-extension

版本:

  • Symfony版本:4.2
  • Twig版本:2.6.2

背景

  • 我正在将现有的PHP应用程序从较旧的symfony版本(2.x)升级到4.2。

这是怎么回事?

我有一个共享服务,该服务已注入并在Controller中使用。

还有一个TwigExtension,它获得注入的相同服务,并期望完全相同的服务实例

  
      
  • 为什么TwigExtension无论如何都依赖于服务是同一实例?      
        
    • 该服务包含TwigExtension处理的特定数据。基本上,该服务目前似乎已被用作一种特定于请求的全局数据容器或数据收集器。
    •   
  •   
  • 在这一点上,您可能会认为这听起来像是一个有问题的做法,并问我为什么实际上在做这样的事情。      
        
    • 我正在处理一个现有应用程序,该应用程序具有现有功能,具体取决于所描述的行为。
    •   
    • 我很乐意第一步使应用程序运行,第二步更改可疑的解决方法。
    •   
  •   

预期行为:

  • 我希望每个请求都将实例化共享服务一次,因此,我也希望TwigExtension接收与控制器完全相同的实例。

实际行为:

  • TwigExtension接收另一个新实例化的服务实例。

旧版本(Symfony 2.x)中的行为:

  • TwigExtension收到了完全相同的服务实例。

我尝试过的事情:

  • 我尝试了使用构造函数注入以及通过在TwigExtension中调用$container->get('service')来获取服务的方法
  • 我在公共场合尝试过:正确/错误
  • 我在其他地方尝试过,例如事件监听器,按预期使用同一服务实例

我的问题:

  • 为什么TwigExtension与控制器注入的服务实例不同?
    • 为什么TwigExtensions与事件侦听器之间的行为不同?
  • 上述预期行为有哪些一般例外?
  • 您能指出我一些有用的文档吗? (当然,我在Google上搜索了很多,并在symfony网站上阅读了相应的文档,但是也许我错过了一些东西?)
  • 您能推荐一种实现相似目标的不同方法吗?

2 个答案:

答案 0 :(得分:2)

因此,事实证明为同一个类定义了两个服务。

在services.yml中手动定义了一项服务,其服务ID为“ service”。在Symfony 2.x时代,手动定义服务是定义服务的唯一方法。

然后出现了自动装配线,基本上用类名称的ID定义了服务。我们可以使用“ bin / console debug:container”来验证这确实是问题所在。这是升级到Symfony 3.4+并启用自动装配的结果。

除了创建服务外,autowire还允许您通过在类名称上键入提示来注入服务。如果在容器中找到匹配的服务ID,则将注入服务。因此,在这种情况下,树枝扩展可能已更改为使用typehinting,而控制器使用$ container-> get导致注入了两个不同的服务。反之亦然。

一种解决方法是使用别名:

# services.yml
MyServiceClassName: service

别名基本上会抑制第二个服务的自动生成。

一种“更好”的方法(或者至少推荐使用)是停止使用$ container-> get,仅在需要时注入服务。然后,您将完全删除“服务”定义。

最后一点,如果服务本身需要任何缩放器构造函数参数(字符串或整数),则自动装配过程将失败并显示一条错误消息。最初,这些错误可能会造成混乱,因为您已经定义了可以正常使用的服务,但是由于服务ID有所不同,因此自动装配会先行尝试并尝试创建一个新的服务。

答案 1 :(得分:0)

我不知道为什么您没有共享服务的相同实例。根据Symfony文档,如果在同一请求中,则应该具有相同的服务实例。

  

在服务容器中,默认情况下所有服务都是共享的。这个   意味着每次检索服务时,您将获得相同的   实例。

如果找不到解决方案,则可以使用两种方法来存储数据。 Session用于简单格式,数据库用于更复杂和长期的存储。