从我的控制器中,我使用
访问应用程序参数(/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似乎是一样的,但我的实际应答是它(来自控制器的参数),我说的是从服务访问。
答案 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)
自2017年起和Symfony 3.4 有更清晰的方式 - 易于设置和使用。
您可以通过它的构造函数 将参数传递给类,而不是使用容器和服务/参数定位器反模式。别担心,这不是时间要求很高的工作,而是设置一次&amp;忘了方法。
如何分两步设置?
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: ..
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()
{
//...
}
我认为这是一种更好的方法。