Aleksandr Khristenko
Подскажите, я туплю и чего-то не могу понять.
Есть интерфейс, и 2 реализации интерфейса. Для одной из реализации объявлен алиас.
Определяю третий сервис в виде
App\C:
class: App\C
arguments:
$a: '@correct_implementation'
Все работает правильно.
Убираю arguments из кода выше и добавляю следущий код в сервис:
public function __construct(
#[Target('correct_implementation')]
private AInterface $a
) {
}
все перестает работать, говорит что не знает какую из реализаций интерфейса надо поставить
Почему оно может не обрабатывать Target в таком случае?
Павел
Aleksandr Khristenko
Aleksandr Khristenko
И как оно вообще может работать как описано в доке вообще непонятно.
Павел
Aleksandr Khristenko
Павел
Автовайринг - это автоматическое определение завимостей, так что вроде я не путаю
Vlad
Павел
Павел
@ibxth Разобрался кажется. Target не про альясы, а про variable name binding
Aleksandr Khristenko
Цитата из доки просто:
Another possibility is to use the #[Target] attribute. By using this attribute on the argument you want to autowire, you can define exactly which service to inject by using its alias.
Павел
Т.е. в target указывается имя переменной, которая уже есть в DI именно имя. Например в примере стоит githubApi. Это говорит не что альяс githubApi а что в DI забинжена переменная githubApi
Павел
Павел
Павел
Павел
Вот так работает
Павел
И в доке написано жирным именно про variable name , меня это и навело на это
Павел
И что есть еще #[Autowire] отдельно
Павел
Павел
Первый скрин это bind раздел
Aleksandr Khristenko
Да хер разберешь, но я протестил
Ну вот если у меня есть
interface ProviderInterface {}
class ProviderA implements ProviderInterface {}
class ProviderB implements ProviderInterface {}
class JobService { public function __construct(ProviderInterface $prodived) {}}
и в сервисах есть
correct_provider:
alias: App\ProviderA
как мне составить Target чтобы оно подхватило?
Павел
Павел
Павел
$shoutyTransformer
Aleksandr Khristenko
Значит дока говно =\
Павел
Только я делал в разделе bind а не просто в сервисе
The Ant
Павел
Павел
Опять же можно если php config название альяса/переменной вывести в константу например
The Ant
та ну хз, сегодня она константа, а завтра будешь по всему коду рыскать где эту константу поменять. Либо тесты писать на каждое применение :D
Павел
Павел
Плюс искать так проще чем по вхождению текста
Павел
Ну т.е. что то типа #[Target(DiVariables:apiMailer)]
Павел
Но в целом мутная история, но наверное все равно лучше чем через название параметров
The Ant
лучше явно биндить в конфиге через
$service->set(Foo::class)
->arg('$bar', service('@bar');
The Ant
Павел
The Ant
или чето другое закинуть по агрументу
Павел
Ты биндишь 1 сервис, там и переменная не нужна
The Ant
нужна, порядок может поменяться
Павел
Ты сервис конфигурируешь, а это конфигурация всего приложения
The Ant
ну я пишу что лучше избегать этого глобала
Павел
Павел
Например есть 2 сервиса которые используются 100 раз под 1 интерфейсом в каждом экшене контрорллера почти
Павел
Будешь каждый контроллер конфигать ручками?
The Ant
🤷♂️ кому как
бегать потом переименовывать, биндить таргетно с той же переменной проблематично
Dmitriy
Павел
зато явно
Но это не удобно. Ровно так же неудобно как потом при каком то рефакторинге эти же 100 сервисов в DI рефачить
Павел
Например тот же Target более чем явно
The Ant
The Ant
тогда ручками :D
Павел
КОроче че спорить, есть возможность, юзать или нет дело каждого. Но соглашусь что механимз ненадежный
Aleksandr Khristenko
Ладно, другой вопрос, может у меня какое-то альтернативное понимание английского.
Но ведь вы тоже строчку Another possibility is to use the #[Target] attribute. By using this attribute on the argument you want to autowire, you can define exactly which service to inject by using its alias. понимаете как возможность заавтовайрить нужный сервис используя его алиас?
Павел
Aleksandr Khristenko
Вопрос не в том, что они подразумевают, а как вы понимаете эту строчку.
Павел
Ну я понял как алиас симфони
Павел
Павел
Чтобы у вас заработало, надо для каждой имплементации создать биндинг на переменную, и использовать имя переменной
Aleksandr Khristenko
>_<
Aleksandr Khristenko
Да мне уже пофиг как нужно сделать, чтобы оно работало. Мне инетерсно, как люди понимают эту строчку документаци. Т.к. в моем понимании сейчас - документация врет.
Павел
Павел
С другой стороны если вчитаться, там много где написано про name
Павел
You must use the interface as the type-hint and the autowiring alias (githubApi) as the variable name:
Павел
Павел
Т.е. это скорее для тех, кто это юзает и им плюшечка
The Ant
Aleksandr Khristenko
Павел
Павел
Эм, не понял.
ну например сделано много каналов логгера и чтобы их использовать через name binding надо везде писать $fooLogger и нельзя поменять название параметра в конструкторе
Павел
А с учетом constructor property promotion это название еще дальше и в код лезет
Павел
И т.е. теперь нейминг в любой части приложения зависит от переменной в di и ломается от любого чиха связанной с именем переменной
The Ant
Эм, не понял.
ну т.е. это это штука чтоб писать переменную как есть ) т.е. описанный тобою кейс
до атрибутов надо биндить в переменную обязательно, а тут нет
Павел
Особенно опасно, если кто то забыл не знал и переименовал переменную в конструкторе и прицепилась дефолтная реализация, в случае с Target - тут всё явно