서비스에서 애플리케이션 매개 변수에 액세스하는 방법은 무엇입니까?
내 컨트롤러에서 나는 응용 프로그램 매개 변수 (에서와 액세스 /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%
또는 비슷한 것? 서비스에서 내 애플리케이션 매개 변수에 어떻게 액세스해야합니까?
이 질문 은 똑같은 것처럼 보이지만 실제로 대답합니다 (컨트롤러의 매개 변수), 서비스에서 액세스하는 것에 대해 이야기하고 있습니다.
서비스 정의에서 매개 변수를 지정하여 다른 서비스를 삽입하는 것과 동일한 방식으로 서비스에 매개 변수를 전달할 수 있습니다. 예를 들어 YAML에서 :
services:
my_service:
class: My\Bundle\Service\MyService
arguments: [%my_param1%, %my_param2%]
여기서 %my_param1%
etc는라는 매개 변수에 해당합니다 my_param1
. 그러면 서비스 클래스 생성자가 다음과 같을 수 있습니다.
public function __construct($myParam1, $myParam2)
{
// ...
}
클린 웨이 2018
2017 년과 Symfony 3.4 이후 훨씬 더 깔끔한 방법이 있습니다. 설정과 사용이 쉽습니다.
컨테이너 및 서비스 / 매개 변수 로케이터 안티 패턴을 사용하는 대신 constructor를 통해 매개 변수를 클래스에 전달할 수 있습니다 . 걱정하지 마세요. 시간이 많이 걸리는 작업이 아니라 한 번 설정하고 접근을 잊어 버립니다 .
2 단계로 설정하는 방법은 무엇입니까?
1. 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"
}
}
즉시 업그레이드 준비!
이전 접근 방식을 사용하는 경우 Rector 를 사용하여 자동화 할 수 있습니다 .
더 읽어보기
이를 서비스 로케이터 접근 방식에 대한 생성자 주입 이라고 합니다.
이에 대해 자세히 알아 보려면 내 게시물 How to Get Parameter in Symfony Controller the Clean Way를 확인하십시오 .
(테스트를 거쳐 새로운 Symfony 메이저 버전 (5, 6 ...)에 대해 계속 업데이트합니다.)
필요한 매개 변수를 하나씩 매핑하는 대신 서비스가 컨테이너에 직접 액세스하도록 허용하지 않는 이유는 무엇입니까? 이렇게하면 서비스와 관련된 새 매개 변수가 추가 된 경우 매핑을 업데이트 할 필요가 없습니다.
그렇게하려면 :
서비스 클래스를 다음과 같이 변경하십시오.
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를 "인수"로 추가하십시오.
services:
my_service_id:
class: ...\MyServiceClass
arguments: ["@service_container"] // <- Add this
언급 된 몇 가지 문제에 대한 해결책으로 배열 매개 변수를 정의한 다음 삽입합니다. 나중에 새 매개 변수를 추가하려면 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.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 .
함께 심포니 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
심포니 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'
여기에 Symfony 3.4가 있습니다.
After some researches, I don't think passing parameters to a class/service via it's constructor, is always a good idea. Imagine if you need to pass to a controller/service some more parameters than 2 or 3. What then? Would be ridiculous to pass, let's say, up to 10 parameters.
Instead, use the ParameterBag
class as a dependency, when declaring the service in yml, and then use as many parameters as you wish.
A concrete example, let's say you have a mailer service, like PHPMailer, and you want to have the PHPMailer connection parameters in the paramters.yml
file:
#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()
{
//...
}
I think this is a better way.
참고URL : https://stackoverflow.com/questions/11209529/how-to-access-an-application-parameters-from-a-service
'program tip' 카테고리의 다른 글
Postgres 프런트 엔드에서 탭을 지정하는 방법 (0) | 2020.11.07 |
---|---|
Makefile에서 스크립트를 소싱하는 방법은 무엇입니까? (0) | 2020.11.07 |
두 개 이상의 인수에 대한 Numpy`logical_or` (0) | 2020.11.07 |
Angular HttpClient "파싱 중 Http 실패" (0) | 2020.11.07 |
jquery에! important를 포함하는 방법 (0) | 2020.11.07 |