Symfony AutoWire несколько сервисов одного класса

я в процессе обновления большого приложения до 4.2

а $this->get(".....") внутри контроллера устарел, и вместо него следует использовать AutoWire.

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

services.yml

services:
  service.a:
    class: Namespace\MyClass
    arguments: [ "argument1" ]

  service.b:
    class: Namespace\MyClass
    arguments: [ "argument2" ]

контроллер:

public function demoAction() {
  $serviceA = $this->get("service.a");
  $serviceB = $this->get("service.b");
}

и проблемный результат:

public function demoAction(MyClass $serviceA, MyClass $serviceB) {
}

мы можем использовать псевдоним для таких определений служб, как:

MyClass: '@service.a'

но я не могу использовать виртуальный / поддельный класс, например (без существующего):

MyPseudClass: '@service.b'

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

Я мог бы создавать «псевдоклассы», которые расширяются от базы, просто чтобы получить другие имена классов, но это кажется странным.

У тебя есть хорошие ответы. Один из подходов, который я иногда использую, - это просто сделать еще два класса MyClassA и MyClassB, оба расширяющиеся от MyClass и в остальном пустые. Затем вы можете ввести подсказку и использовать autowire, чтобы вообще избежать записи в services.yaml.

Cerad 30.11.2018 14:10

да, я знаю, пробовал, работает, но меньше кода - лучший код!

Helmut Januschka 30.11.2018 14:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
13
2
4 541
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Начиная с версии 4.2, вы можете определять именованные псевдонимы автоподключения. Это должно работать:

services:
    Namespace\MyClass $serviceA: '@service.a'
    Namespace\MyClass $serviceB: '@service.b'

В Symfony 3.4 и 4.1 вы можете вместо этого использовать привязки, но это менее конкретно, поскольку не принимает во внимание тип:

services:
    _defaults:
        bind:
            $serviceA: '@service.a'
            $serviceB: '@service.b'

спасибо - это работает, поэтому я использую псевдоним, выглядит нормально и работает. в некоторых местах я полагаюсь на тот факт, что services_dev.yml изменяет класс некоторых служб, поэтому "тип" нестабилен, поэтому я использую для них способ привязки. Является ли привязка надежным способом в будущем? или скоро он станет нерекомендуемым?

Helmut Januschka 30.11.2018 12:59

Думаю, вы имели в виду services: _defaults: bind: Namespace\MyClass $serviceA: '@service.a' Namespace\MyClass $serviceB: '@service.b':?

medunes 29.03.2019 17:53

Вы по-прежнему можете использовать "@servicename" в файлах service.yml, и поэтому подключайте их по имени / Вот пример, где у меня есть несколько разных регистраторов, подключенных к конструктору службы.

# App/Subscribers/WebhookLoggingListener.php file
public function __construct(
    LoggerInterface $logger, 
    LoggerInterface $mailgunLog
{ }

# services.yml
App\Subscribers\WebhookLoggingListener:
    arguments:
        $logger: "@logger"
        $mailgunLog: "@monolog.logger.mailgun"
    tags:
       - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest

Вы также можете привязать их к именам переменных (в services: _defaults: во главе файла services.yaml, но если они не будут использоваться повторно, я считаю, что лучше сохранить конфигурацию более локализованной).

Другой вариант - реализовать Заводской образец. Этот шаблон позволит вам создать службу на основе предоставленных аргументов.

# services.yml
service.a:
    class: App\MyClass
    factory: 'App\Factory\StaticMyClassFactory:createMyClass'
    arguments:
        - ['argument1']

service.b:
    class: App\MyClass
    factory: 'App\Factory\StaticMyClassFactory:createMyClass'
    arguments:
        - ['argument2']

И ваш StaticMyClassFactory будет выглядеть так

class StaticMyClassFactory
{  
    public static function createMyClass($argument)
    {
        // Return your class based on the argument passed
        $myClass = new MyClass($argument);

        return $myClass;
    }
}

Другие вопросы по теме