【问题标题】:Symfony 5 inject service by aliasSymfony 5 通过别名注入服务
【发布时间】:2020-09-21 15:33:54
【问题描述】:

我有一个服务叫:

<?php
class CustomService
{
    private $string;
    private $service1;
    private $service2;
    
    public function __construct($string, Service1 $service1, Service2 $service2)
    {
        $this->string = $string;
        $this->service1 = $service1;
        $this->service2 = $service2;
    }

    //Custom functions
}

$string 参数是一个可以改变其值的字符串。

我想从其他服务调用此服务,但有没有办法在我的 services.yaml 中使用某种别名定义“CustomService”?

service:
    App\Service\CustomService:
        alias: preService1
        arguments:
            $string: 'ABCD'
    
    App\Service\CustomService:
        alias: preService2
        arguments:
            $string: 'EFGH'

并在另一个服务中注入由别名定义的服务之一:

<?php
class PurchaseService
{
    public function __construct(CustomService $preService1)
    {
        //Here $preService1->string must be 'ABCD'
    }
    
    //Or in other functions in this service $preService1->string must be 'ABCD'
}

【问题讨论】:

    标签: php symfony symfony5


    【解决方案1】:

    根据Symfony documentation可以创建别名:

    #service.yml
    
    preService1:
        class: App\Service\CustomService:
        autowire: false
        arguments:
            $string: 'ABCD'
    
    preService2:
        class: App\Service\CustomService:
        autowire: false
        arguments:
            $string: 'EFGH'
    

    【讨论】:

    • autowire: false 是多余的。此外,在这种情况下,您必须设置其他依赖项(Service1 和 Service2)
    • @BoShurik autowire: false 并不是多余的,因为它只是错误的。保持它为真(默认)意味着可以自动装配附加参数。它仍然没有完全回答 PurchaseService 还需要服务定义的问题。有点希望这不是一个问题。有了一点反馈,就可以得出一个实际的答案。哦,好吧。
    【解决方案2】:

    我刚刚遇到了一个非常相似的问题,这就是我得到的解决方案。您需要将 CustomService 的别名注入 PurchasService。

    没有必要禁用自动连线,因此仍会自动连线附加参数。

    service:
        app.service.pre_service1:
            class: App\Service\CustomService
            arguments:
                $string: 'ABCD'
                
        app.service.pre_service2:
            class: App\Service\CustomService
            arguments:
                $string: 'EFGH'
                
        app.service.purchase_service:
            class: App\Service\PurchaseService
            arguments:
                $preService1: '@app.service.pre_service1'
                
        App\Service\PurchaseService:
            alias: app.service.purchase_service
    

    【讨论】:

      【解决方案3】:

      我无法发表评论,因此我将其发布为答案。 除非我错过了什么,否则你有不同的看法。 您可以扩展一个基类来实现字符串功能(或者如果 $string 是您唯一需要的,则使用 Trait)。

      您也可以使用工厂退回您需要的服务

      Factory::getCustomService($string) {
        $customService = createCustomService();
        $customService->setString($string);
        return $customService;
      }
      

      我不确定你以后会如何使用它,但乍一看似乎有点奇怪,所以如果你不希望在实例化服务后设置这个变量,我会推荐使用工厂或使用继承。

      最简单的可能是:

      <?php
      class PurchaseService
      {
          public function __construct(CustomService $preService1)
          {
              $preService1->setString ('ABCD');
          }
          
          //Or in other functions in this service $preService1->string must be 'ABCD'
      }
      

      【讨论】:

      • 好的,我试试看
      • 您不能发表评论并不意味着您应该发布偏离主题的答案。 Symfony 有自己的做事方式。希望操作员不会在您的方法上浪费太多时间。
      • @Cerad 我很高兴就建设性的讨论进行辩论。我的方法适用于 Symfony,所以我很想知道哪种方法更好,这样我也可以改进。你的解决方案是什么?我阅读了自动装配错误解决方案,它确实也可以,但你仍然需要调用两个不同的服务。我想这取决于个人喜好,但老实说,我很高兴能更好地理解您的想法
      • 您的回答忽略了创建服务所需的其他参数。它也忽略了使用 Symfony 服务定位器的可能性。您的方法基本上无视整个 Symfony DI 容器,这就是问题所在。但谁知道呢。也许它会被接受。
      • 好吧,我明白你的意思。面对类似的情况,我可能会使用自动装配和继承来维护 DI。这也意味着更少的 yaml 配置。在您的观点中,自动装配 false 的 .Ain 优势是什么(真正的问题)。
      猜你喜欢
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      • 2019-04-17
      • 1970-01-01
      • 2018-01-22
      • 1970-01-01
      • 2021-09-15
      相关资源
      最近更新 更多