я в процессе обновления большого приложения до 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?
Я мог бы создавать «псевдоклассы», которые расширяются от базы, просто чтобы получить другие имена классов, но это кажется странным.
да, я знаю, пробовал, работает, но меньше кода - лучший код!




Начиная с версии 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 изменяет класс некоторых служб, поэтому "тип" нестабилен, поэтому я использую для них способ привязки. Является ли привязка надежным способом в будущем? или скоро он станет нерекомендуемым?
Думаю, вы имели в виду services: _defaults: bind: Namespace\MyClass $serviceA: '@service.a' Namespace\MyClass $serviceB: '@service.b':?
Вы по-прежнему можете использовать "@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;
}
}
У тебя есть хорошие ответы. Один из подходов, который я иногда использую, - это просто сделать еще два класса MyClassA и MyClassB, оба расширяющиеся от MyClass и в остальном пустые. Затем вы можете ввести подсказку и использовать autowire, чтобы вообще избежать записи в services.yaml.