Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP/Symfony:为什么TwigExtension注入的服务实例与控制器不同? 版本: Symfony版本:4.2 小枝版本:2.6.2 背景 我正在将一个现有的PHP应用程序从一个非常旧的symfony版本(2.x)升级到4.2 发生什么事?_Php_Symfony_Twig_Twig Extension - Fatal编程技术网

PHP/Symfony:为什么TwigExtension注入的服务实例与控制器不同? 版本: Symfony版本:4.2 小枝版本:2.6.2 背景 我正在将一个现有的PHP应用程序从一个非常旧的symfony版本(2.x)升级到4.2 发生什么事?

PHP/Symfony:为什么TwigExtension注入的服务实例与控制器不同? 版本: Symfony版本:4.2 小枝版本:2.6.2 背景 我正在将一个现有的PHP应用程序从一个非常旧的symfony版本(2.x)升级到4.2 发生什么事?,php,symfony,twig,twig-extension,Php,Symfony,Twig,Twig Extension,我有一个共享的服务,它被注入并在我的控制器中使用 还有一个TwigExtension,它注入了相同的服务,并期望得到完全相同的服务实例 为什么TwigExtension仍然依赖服务作为同一实例? 该服务包含TwigExtension处理的特定数据。基本上,该服务目前似乎被用作特定于请求的全局数据容器或数据收集器 在这一点上,你可能会说,这听起来像是一个可疑的做法,并问我为什么要这样做。 我正在处理一个现有的应用程序,其功能取决于所描述的行为 我很乐意让应用程序在第一步工作,并在第二步改变

我有一个共享的服务,它被注入并在我的控制器中使用

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

  • 为什么TwigExtension仍然依赖服务作为同一实例?
    • 该服务包含TwigExtension处理的特定数据。基本上,该服务目前似乎被用作特定于请求的全局数据容器或数据收集器
  • 在这一点上,你可能会说,这听起来像是一个可疑的做法,并问我为什么要这样做。
    • 我正在处理一个现有的应用程序,其功能取决于所描述的行为
    • 我很乐意让应用程序在第一步工作,并在第二步改变可疑的解决方法
预期行为:
  • 我期望一个共享服务在每个请求中被完全实例化一次,因此我也期望TwigExtension接收与控制器完全相同的实例
实际行为:
  • TwigExtension接收一个新实例化的不同服务实例
旧版本中的行为(Symfony 2.x):

  • TwigExtension收到了完全相同的服务实例
我尝试的是:
  • 我在TwigExtension中通过调用
    $container->get('service')
    尝试了构造函数注入和获取服务
  • 我在公众面前试过:对/错
  • 我在其他地方尝试过,比如事件监听器,,在这些地方按照预期使用了相同的服务实例
我的问题是:
  • 为什么TwigExtension注入的服务实例与控制器不同?
    • 为什么TwigExtensions和例如事件侦听器之间存在不同的行为
  • 上述预期行为有哪些一般例外情况
  • 你能给我指一些有用的文件吗?(当然,我在谷歌上搜索了很多,并在symfony网站上阅读了相应的文档,但也许我错过了什么?)
  • 你能推荐一种不同的方法来实现类似的目标吗

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

      在服务容器中,默认情况下共享所有服务。这 意味着每次检索服务时,都会得到相同的结果 例如


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

      因此,原来两个服务是为同一类定义的

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

      然后autowire出现了,它基本上用类名的id来定义服务。我们能够使用“bin/console debug:container”验证这确实是问题所在。这是升级到Symfony 3.4+并启用autowire的结果

      除了创建服务外,autowire还允许您通过对类名进行类型提示来注入服务。如果在容器中找到匹配的服务id,则注入该服务。因此,在本例中,当控制器使用$container->get时,细枝扩展可能被更改为使用typehinting,从而导致注入两个不同的服务。或者反之亦然

      一种修复方法是使用别名:

      # services.yml
      MyServiceClassName: service
      
      别名将基本上抑制第二个服务的自动生成

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


      最后请注意,如果服务本身需要任何scaler构造函数参数(字符串或int),则autowire进程将失败并显示错误消息。这些错误一开始可能会很混乱,因为您已经定义了一个正常工作的服务,但由于服务id不同,autowire只是向前推进并尝试创建一个新的服务。

      是的,我在文档中知道这个声明,这就是我不理解其行为的原因。运行“bin/console debug:container service”并验证Shared是否设置为Yes。然后重复“bin/console debug:container FullyQualifiedServiceClassName”,我怀疑您的类有两个服务副本,类型提示用于扩展,get('service')用于控制器。猜猜看。@Cerad非常感谢你!跟你怀疑的一模一样。我的服务确实注册了两次。一次使用别名,一次使用完全限定名(自动连线)。原因是,实际注册没有标记为别名。我只需将
      别名:full\Qualified\ServiceName
      添加到yaml文件中的现有注册中。我建议你将此作为答案发布。我将它标记为正确的解决方案:)