[php] 서비스에서 애플리케이션 매개 변수에 액세스하는 방법은 무엇입니까?

내 컨트롤러에서 나는 응용 프로그램 매개 변수 (에서와 액세스 /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

2018 년과 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


답변

심포니 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 .


답변

언급 된 몇 가지 문제에 대한 해결책으로 배열 매개 변수를 정의한 다음 삽입합니다. 나중에 새 매개 변수를 추가하려면 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 솔루션은 매우 간단합니다.

다음은 원본 게시물의 일부입니다.

// 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


답변

@richsage는 정확하지만 (Symfony 3.?) 내 Symfony 4.x에서는 작동하지 않았습니다. 여기에 Symfony 4가 있습니다.

services.yaml 파일

parameters:
    param1: 'hello'

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

서비스 클래스 routineCheck.php 파일에서 이렇게 생성자를 수행하십시오.

private $toBechecked;

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

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

끝난.