如何从服务访问应用程序参数?

时间:2012-06-26 14:24:09

标签: php symfony yaml

从我的控制器中,我使用

访问应用程序参数(/app/config中的那些参数)
$this->container->getParameter('my_param')

但我不知道如何从服务访问它(我想我的服务类不应该扩展Symfony\Bundle\FrameworkBundle\Controller\Controller)。

我应该将所需的参数映射到我的服务注册中,如下所示:

#src/Me/MyBundle/Service/my_service/service.yml
parameters:
    my_param1: %my_param1%
    my_param2: %my_param2%
    my_param3: %my_param3%

或类似的东西?我应该如何从服务中访问我的应用程序参数?


This question似乎是一样的,但我的实际应答是它(来自控制器的参数),我说的是从服务访问。

9 个答案:

答案 0 :(得分:113)

您可以通过在服务定义中指定参数,以与注入其他服务相同的方式将参数传递给服务。例如,在YAML中:

services:
    my_service:
        class:  My\Bundle\Service\MyService
        arguments: [%my_param1%, %my_param2%]

其中%my_param1%等对应于名为my_param1的参数。然后你的服务类构造函数可以是:

public function __construct($myParam1, $myParam2)
{
    // ...
}

答案 1 :(得分:18)

为什么不允许您的服务直接访问容器,而不是逐个映射您需要的参数?这样做,如果添加了新参数(与您的服务相关),则无需更新映射。

这样做:

对服务类进行以下更改

use Symfony\Component\DependencyInjection\ContainerInterface; // <- Add this

class MyServiceClass
{
    private $container; // <- Add this
    public function __construct(ContainerInterface $container) // <- Add this
    {
        $this->container = $container;
    }
    public function doSomething()
    {
        $this->container->getParameter('param_name_1'); // <- Access your param
    }
}

在services.yml

中添加@service_container作为“arguments”
services:
  my_service_id:
    class: ...\MyServiceClass
    arguments: ["@service_container"]  // <- Add this

答案 2 :(得分:17)

清洁方式2018

自2017年起和Symfony 3.4 有更清晰的方式 - 易于设置和使用。

您可以通过它的构造函数 将参数传递给类,而不是使用容器和服务/参数定位器反模式。别担心,这不是时间要求很高的工作,而是设置一次&amp;忘了方法。

如何分两步设置?

1。 config.yml

# config.yml

# config.yml
parameters:
    api_pass: 'secret_password'
    api_user: 'my_name'

services:
    _defaults:
        autowire: true
        bind:
            $apiPass: '%api_pass%'
            $apiUser: '%api_user%'

    App\:
        resource: ..

2。任何Controller

<?php declare(strict_types=1);

final class ApiController extends SymfonyController
{
    /**
     * @var string 
     */
    private $apiPass;

    /**
     * @var string
     */
    private $apiUser;

    public function __construct(string $apiPass, string $apiUser)
    {
        $this->apiPass = $apiPass;
        $this->apiUser = $apiUser;
    }

    public function registerAction(): void
    {
        var_dump($this->apiPass); // "secret_password"
        var_dump($this->apiUser); // "my_name"
    }
}

即时升级就绪!

如果您使用旧方法,可以automate it with Rector

了解更多

这称为构造函数注入服务定位器方法。

要详细了解此信息,请查看我的帖子How to Get Parameter in Symfony Controller the Clean Way

(经过测试,我保持更新为新的Symfony主要版本(5,6 ...))。

答案 3 :(得分:6)

作为上述一些问题的解决方案,我定义了一个数组参数然后注入它。稍后添加新参数只需要添加参数数组,而无需对service_container参数或构造进行任何更改。

延伸@richsage回答:

parameters.yml

parameters:
    array_param_name:
        param_name_1:   "value"
        param_name_2:   "value"

services.yml

services:
    my_service:
        class:  My\Bundle\Service\MyService
        arguments: [%array_param_name%]

然后访问类

public function __construct($params)
{
    $this->param1 = array_key_exists('param_name_1',$params)
        ? $params['param_name_1'] : null;
    // ...
}

答案 4 :(得分:3)

从symfony 4.1开始,有一种非常干净的新方法可以实现它

<?php
// src/Service/MessageGeneratorService.php

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MessageGeneratorService
{
 private $params;
 public function __construct(ParameterBagInterface $params)
 {
      $this->params = $params;
 }
 public function someMethod()
 {
     $parameterValue = $this->params->get('parameter_name');
...
 }
}

来源:https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service

答案 5 :(得分:2)

使用 Symfony 4.1 ,该解决方案非常简单。

这是原始文章的摘录:

// src/Service/MessageGenerator.php
// ...

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MessageGenerator
{
    private $params;

    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    public function someMethod()
    {
        $parameterValue = $this->params->get('parameter_name');
        // ...
    }
}

链接到原始帖子: https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service

答案 6 :(得分:0)

在symfony 4中,我们可以通过依赖注入来访问参数:

服务:

   use Symfony\Component\DependencyInjection\ContainerInterface as Container;

   MyServices {

         protected $container;
         protected $path;

         public function __construct(Container $container)
         {
             $this->container = $container;
             $this->path = $this->container->getParameter('upload_directory');
         }
    }

parameters.yml:

parameters:
     upload_directory: '%kernel.project_dir%/public/uploads'

答案 7 :(得分:0)

@richsage是正确的(适用于Symfony 3.?),但不适用于我的Symfony4.x。所以这里是Symfony 4。

在services.yaml文件中

parameters:
    param1: 'hello'

Services:
    App\Service\routineCheck:
            arguments:
                $toBechecked: '%param1%'  # argument must match in class constructor

在您的服务类例程中,CheckCheck.php文件像这样构造函数

private $toBechecked;

public function __construct($toBechecked)
{
    $this->toBechecked = $toBechecked;
}

public function echoSomething()
{
    echo $this->toBechecked;
}

完成。

答案 8 :(得分:-1)

这里是Symfony 3.4。

经过一些研究,我不认为通过其构造函数将参数传递给类/服务总是一个好主意。 想象一下,如果您需要向控制器/服务传递比2或3更多的参数。假设最多传递10个参数,将是非常荒谬的。

相反,在yml中声明服务时,请使用ParameterBag类作为依赖项,然后根据需要使用任意数量的参数。

一个具体示例,假设您有一个邮件服务,例如PHPMailer,并且您想在paramters.yml文件中包含PHPMailer连接参数:

#parameters.yml
parameters:
    mail_admin: abc@abc.abc
    mail_host: mail.abc.com
    mail_username: noreply@abc.com
    mail_password: pass
    mail_from: contact@abc.com
    mail_from_name: contact@abc.com
    mail_smtp_secure: 'ssl'
    mail_port: 465

#services.yml
services:
    app.php_mailer:
        class: AppBundle\Services\PHPMailerService
        arguments: ['@assetic.parameter_bag'] #here one could have other services to be injected
        public: true

# AppBundle\Services\PHPMailerService.php
...
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
...
class PHPMailerService
{
    private $parameterBag;
    private $mailAdmin;
    private $mailHost;
    private $mailUsername;
    private $mailPassword;
    private $mailFrom;
    private $mailFromName;
    private $mailSMTPSecure;
    private $mailPort;
}
public function __construct(ParameterBag $parameterBag)
{
    $this->parameterBag = $parameterBag;

    $this->mailAdmin      = $this->parameterBag->get('mail_admin');
    $this->mailHost       = $this->parameterBag->get('mail_host');
    $this->mailUsername   = $this->parameterBag->get('mail_username');
    $this->mailPassword   = $this->parameterBag->get('mail_password');
    $this->mailFrom       = $this->parameterBag->get('mail_from');
    $this->mailFromName   = $this->parameterBag->get('mail_from_name');
    $this->mailSMTPSecure = $this->parameterBag->get('mail_smtp_secure');
    $this->mailPort       = $this->parameterBag->get('mail_port');
}
public function sendEmail()
{
    //...
}

我认为这是一种更好的方法。