Wpis z mikrobloga

Czy są na wykopie specjaliści od #symfony #symfony3 ?
Mam apkę w legacy code, którą refaktoruję na coś znośnego. Jest już router, wprowadziłem też kontener DI, pobieram z niego serwisy w kontrolerze (przed wywołaniem kontrolera wstrzykuję kontener do kontrolera). Mogę sobie też pobierać parametry w kontrolerach i przekazywać je do serwisów.
Mam jednak pewien problem:
Otóż nie mogę sobie wstrzyknąć serwisu do kontrolera jako argument metody. Jak próbuję to zrobić to rzuca mi wyjątkiem:

Controller "APP\V2\Controller\API\TestController::initAction()" requires that you provide a value for the "$facebookService" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
Nie wiem jak zmusić DI do wstrzykiwania zależności do metod. Już zamieniłem kontrolery na serwisy. W kontenerze mam wszystkie serwisy i kontrolery, ale nie wiem czego mi jeszcze brakuje do tego, żeby to zadziałało.

Pytania są 2:
1. Da się jakoś inaczej przekazać kontener do serwisu? Bo to co mam w Framework::handle(), to średnio mi się podoba.
2. W jaki sposób zmusić kod do wstrzyknięcia zależności do metody. Przecież mam wszystko zadeklarowane jako serwisy, wszystko ładuję z kontenera, więc powinienem tam mieć już wszystkie serwisy itd. Mam też włączone opcje autoconfigure i autowire. Czego jeszcze mi brakuje?

Przygotowałem tu gista. Jeżeli są jakieś błędy w namespacach, to proszę na to nie zwracać uwagi. Po prostu wywaliłem nazwy projektu z namespace.
https://gist.github.com/miedzwin/49bac1cc1d5270d3ba1bfcf700abf864

#php #webdev #webdevhelp
  • 11
  • Odpowiedz
Otóż nie mogę sobie wstrzyknąć serwisu do kontrolera jako argument metody.


@mariecziek: Nie można przekazywać zależności jako argumenty metod. Zrób to w konstruktorze. I nie wstrzykuj całego kontenera, tylko poszczególne serwisy.
  • Odpowiedz
@Jake_921: jak dam takie coś:

public function __construct(FacebookService $facebookService){}
to mam taki błąd:

Too few arguments to function ApiController::__construct(), 0 passed in /var/wwwl/vendor/symfony/http-kernel/Controller/ControllerResolver.php on line 133 and exactly 1 expected
Jedyny sposób w tej chwili na dostanie się do serwisu, to $this->container->get(FacebookService::class);
A ja chcę to wstrzykiwać, a nie wyciągać z kontenera.

Proponujesz opisywać w services.yml każdy kontroller i wpisywać tam metoda: wstrzykiwany_serwis?
  • Odpowiedz
@mariecziek: Wygląda na to że ten kontroler nie jest w ogóle zarejestrowany jako serwis. W przeciwnym razie argument zostałby przekazany automatycznie (bo w services.yml masz włączone autowiring i autoconfigure).

Odpal bin/console debug:container i zobacz czy jest na liście.
  • Odpowiedz
@mariecziek: Jeśli masz komponenty symfony/debug i symfony/console to zadziała :) Ale ok, rozumiem.

Ten kod który masz teoretycznie powinien działać po przeniesieniu zależności do kontrolera, ale widać coś jeszcze jest nie tak. Winy szukałbym w services.yml. Może zła ścieżka? Sprawdź też może czy inne serwisy, nie będące kontrolerami działają - utwórz jakiś, który miałby korzystać z tego FacebookService i sprawdź czy jest poprawnie inicjalizowany. Jeśli zadziała, to wina może leżeć w
  • Odpowiedz
Nie można przekazywać zależności jako argumenty metod.


@Jake_921: jak nie można jak można? Właśnie sprawdziłem, na wersji 4.1 wszystko działa. Coś się zmieniło w stosunku do trójki?
  • Odpowiedz
@croppz: Jak rozumiem mówisz o tym? https://symfony.com/doc/current/service_container/calls.html

Faktycznie, jest taka możliwość i zapomniałem o niej. Jednak szczerze mówiac nie widziałem aby gdzieś się to stosowało w praktyce. Jest to też trochę coś innego niż OP chce, bo tutaj argument jest wstrzykiwany przy inicjalizacji serwisu i wtedy też jest ta metoda wykonywana, a w przypadku OPa mowa o akcji w kontrolerze wywoływanej przez routing.
  • Odpowiedz
@Jake_921: No nie zadziałało…
Mam taki komunikat:

The "APP\V2\Service\TestService" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.
  • Odpowiedz