Как получить доступ к параметрам приложения с сервиса?


из моих контроллеров я получаю доступ к параметрам приложения (те, что в /app/config) С

$this->container->getParameter('my_param')

но я не знаю, как получить доступ к нему из службы (я предполагаю, что мой класс обслуживания не должен расширяться SymfonyBundleFrameworkBundleControllerController).

Я должен сопоставить необходимые параметры в моей регистрации службы, как это:

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

или что-то подобное? Как получить доступ к параметрам приложения из службы?


этот вопрос похоже на то же самое, но мой на самом деле отвечает на него (параметры от контроллера), я говорю о доступе из службы.

4 62

4 ответа:

вы можете передавать параметры в свой сервис так же, как вы вводите другие сервисы, указав их в своем определении сервиса. Например, в YAML:

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

здесь %my_param1% etc соответствует параметру с именем my_param1. Тогда ваш конструктор класса обслуживания может быть:

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

вместо того, чтобы сопоставлять ваши необходимые параметры один за другим, почему бы не разрешить вашему сервису напрямую обращаться к контейнеру? При этом вам не нужно обновлять сопоставление, если добавлены новые параметры (которые относятся к вашему сервису).

для этого:

внесите следующие изменения в свой класс обслуживания

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

добавить @service_container в качестве" аргументов " в ваших службах.в формате YML

services:
  my_service_id:
    class: ...\MyServiceClass
    arguments: ["@service_container"]  // <- Add this

Чистый Путь 2018

С 2017 года и Symfony 3.4 есть гораздо более чистый способ-простота установки и использования.

вместо того, чтобы использовать контейнер и сервис/параметр локатор анти-шаблон, вы можете передать параметры в класс через его конструктор. Не волнуйтесь, это не трудоемкая работа, а скорее настройка один раз и забыть подход.

как настроить его в 2 шага?

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"
    }
}

Мгновенное Обновление Готово!

в случае, если вы используете более старый подход, вы можете автоматизировать его с ректором.

Подробнее

это называется инъекция конструктора через локатор служб подход.

читать больше об этом, проверьте мой пост как получить параметр в контроллере Symfony чистым способом.

(это протестировано, и я продолжаю обновлять его для новой версии Symfony major (5, 6...)).

как решение некоторых из упомянутых проблем, я определяю параметр массива, а затем вводим его. Добавление нового параметра позже просто требует добавления в массив параметров без какого-либо изменения аргументов service_container или конструкции.

Так что расширение на @richsage ответ:

параметры.в формате YML

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

услуги.в формате 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;
    // ...
}