在不将参数传递给子类的情况下共享Symfony服务中的依赖项 - php

我的许多服务都依赖于与外部数据库的PDO连接(由于特定于我的应用程序的原因,使用这种策略要比使用Doctrine有意义。)要启动PDO连接,每个服务都需要一个数据源名称,用户名和密码。这使我的services.yml包含每个服务的许多相同参数:

#AppBundle\Resources\config\services.yml

    # ...

    QueryDataBuilderHelper:
        class: AppBundle\Services\QueryDataBuilderHelper
        arguments: [ "%database_host%", "%database_user%", "%database_password%" ]

    ZipCodeClass:
        class: AppBundle\Services\ZipCodeClass
        arguments: [ "%database_host%", "%database_user%", "%database_password%" ]

    # ...

是否可以在某处定义连接并在所有服务中引用该连接,而无需将参数传递给每个服务?

Symfony cookbook建议使用父服务并扩展父服务。当我尝试使用子类时,子类不会提取超类的参数:

#AppBundle\Resources\config\services.yml

DBConnectionHelper:
    class: AppBundle\Services\DBConnectionHelper
    arguments: [ "%database_host%", "%database_user%", "%database_password%" ]


DBSubClass:
    class: AppBundle\Services\DBSubClass
    parent: DBConnectionHelper
    arguments: [ "%unrelated_parameter%" ] 
//AppBundle\Services\SuperClassService.php

namespace AppBundle\Services;

class DBConnectionHelper
{
    public function __construct($dsn, $user, $password){
        $this->DB_connection = new \PDO($dsn, $user, $password);
    }
}
//AppBundle\Services\DBSubClass.php

namespace AppBundle\Services;

class DBSubClass extends DBConnectionHelper
{
    public function __construct($unrelated_param){
        //Calling parent::__construct() here will require the parameters again. 
        //Which is what I am trying to avoid...

        // Outputs a notice that DB_Connection isn't set.
        var_dump($this->DB_Connection());

        $this->unrelated_param = $unrelated_param;
    }
}

我在这里使用了构造函数而不是setter,因为这些依赖关系不是可选的。 Symfony docs建议仅在依赖关系是可选的时才使用setter。

参考方案

您在这里需要使用的称为Abstract Service。幸运的是,Symfony提供了一种实现此目标的方法。您要查找的选项是abstractparent。您可以阅读整章here.

我将尝试从文档中简要解释该示例,以便您可以理解这个想法。

# ...
services:
    # ...
    mail_manager:
        abstract:  true
        calls:
            - [setMailer, ["@my_mailer"]]
            - [setEmailFormatter, ["@my_email_formatter"]]

    newsletter_manager:
        class:  "NewsletterManager"
        parent: mail_manager

    greeting_card_manager:
        class:  "GreetingCardManager"
        parent: mail_manager

基本上,您需要执行以下操作:

创建一个抽象类,在其中定义所有通用属性/方法。
然后在服务文件中相应配置这些通用方法调用,并添加选项abstract。由于您的服务是abstract服务,这意味着它无法实例化,因此此处的class选项被省略。
之后,像往常一样创建一个服务,不要忘记extend抽象类。然后通过设置抽象服务的名称在service.yml文件中注册该服务并向其中添加parent选项。
对于每个儿童服务,您可以根据需要多次重复上述步骤,您应该一切顺利。

如有任何疑问,请发表评论。希望这可以帮助您。

PHP Count数组元素 - php

嗨,有人可以解释为什么这会返回“数组由0个元素组成”。 :$arr = array(1,3,5); $count = count($arr); if ($count = 0) { echo "An array is empty."; } else { echo "An array has $count elements.…

PHP:从函数返回值并直接回显它? - php

这可能是一个愚蠢的问题,但是……的PHPfunction get_info() { $something = "test"; return $something; } html<div class="test"><?php echo get_info(); ?></div> 有没有办…

Symfony 2在用户站点上动态添加字段以形成表单 - php

我正在研究调查包。目的是为用户提供一个功能全面的调查系统。我已经准备好一个后端,使您可以创建调查,添加问题(打开文本,单选按钮,复选框),是否需要提问,激活调查,生成令牌以及通过电子邮件将令牌发送到调查的链接。当然,我也有显示调查并保存答案的前端。现在,我想添加另一种可能性。带有答案(单选或复选框)和评论的问题。例如:你有一只狗吗?是没有如果用户选择是,则附…

PHP:将数据从二维数组复制到一维数组的最快方法 - php

我有一个巨大的二维PHP数组,带有500万行。$t = [ [ "id" => 1, "name" => "foo" ], [ "id" => 2, "name" => "bar" ] ]; 现在,我必须将此数组的I…

php-printf和sprintf具有不同的输出 - php

我编写了以下微型php程序来测试printf和sprintf:<?php $str_1 = printf("%x%x%x", 65, 127, 245); $str_2 = sprintf("%x%x%x", 65, 127, 245); echo $str_1 . "\n"; echo $s…