Метод возвращает значение в качестве служебного параметра

#symfony

#symfony

Вопрос:

Я пытаюсь использовать метод-return-value в качестве параметра DI. Конкретный вариант использования заключается в том, что у меня есть сервис, который имеет логику вычисления кода страны пользователя, например:

 $user->getCountryCode();
 

С другой стороны, у меня есть много сервисов, которые зависят от страны, например:

 $foo = new Foo('UK');
$bar = new Bar('USA');
 

Я знаю, что могу ввести пользовательский сервис в Foo / Bar, но это создает странную зависимость, поскольку этим службам не нужен пользователь, им просто нужен код страны.

Есть ли у меня способ написать описание сервиса в соответствии с:

   my_services.foo:
    class: Foo
    arguments:
      - @user.getCountryCode
 

Редактировать:
Я использую symfony 2.4 с конфигурацией yml.

Ответ №1:

Метод фабрики сервисов (совместим со всеми версиями Symfony2)

Определения служб:

 # services.yml

FooFactory:
  class: FooFooBundleServiceFooFactory
  arguments: [@user_country_code_calc_service]

FooService:
  class: FooFooBundleServiceFooService
  factory_service: FooFactory
  factory_method: create
 

И ваша фабрика:

 // FooFactory.php

class FooFactory
{
    private $countryCodeCalculator;

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

    public function create()
    {
        $countryCode = $this->countryCodeCalculator->calculate(...);

        return new FooService($countryCode);
    }
}
 

Теперь, когда вы вводите @FooFactory любой из своих сервисов, Symfony фактически вызовет FooFactory::create и введет в него результат этого метода.

Ответ №2:

Метод языка выражений (совместим с версиями Symfony> = 2.4)

 # services.yml

foo_service:
  class: FooFooBundleServiceFooService
  arguments: ["=service('user_countrycode_calc_service').calculateCountryCode()"]
 

Комментарии:

1. Это не позволит мне вводить «скалярные» значения, поскольку для службы требуется допустимый класс.

2. удалить @ из начала аргумента, я допустил опечатку

3. На самом деле @ это необходимо (как показано в документации ). Я лично использую его только для включения метода MasterRequest ( "GET" / "POST" ..), и он работает : "@=service('request_stack').getMasterRequest().getMethod()"