Praktický návod

Jak správně používat Dependency Injection v Symfony

Třída nemá potají vyrábět vše, co potřebuje. Nech jí závislosti předat a bude se lépe testovat i měnit.

15 minut · Symfony

Nejdřív stručně

O co jde?

Dependency Injection znamená, že si třída nevytváří například logger nebo klienta databáze sama. Dostane je zvenku, nejčastěji v konstruktoru.

Service je objekt, který dělá jednu užitečnou práci. Container v Symfony služby vytvoří, propojí a podle typu je umí automaticky předat tam, kde jsou potřeba.

Připrav si

Co budeš potřebovat

Stačí běžící Symfony projekt a jedna malá služba, kterou chceš použít z kontroleru nebo jiného objektu.

  • Symfony projekt se standardní konfigurací services.yaml.
  • Jednu konkrétní odpovědnost. Třeba sestavení čísla objednávky nebo odeslání notifikace.
  • Rozhraní tam, kde chceš skrýt konkrétního dodavatele, například e-mailovou nebo platební službu.
  • Základní test nebo místo, odkud službu zavoláš. Díky němu hned zjistíš, zda je propojená správně.

Kroky 1 až 3

Předávej závislosti jednoduše

Začni konstruktorovou injekcí. Je čitelná, povinné závislosti jsou na první pohled vidět a dobře se testuje.

1. Vytvoř malou službu

  1. Do src/Service dej třídu s jedním jasným úkolem. Název popisuj podle práce, ne podle technologie.
  2. Nedávej do ní HttpFoundation Request ani celý container jen proto, že se to zrovna hodí. Potřebná data předej metodě.
  3. Pokud služba potřebuje jinou službu, přidej ji jako typovaný argument konstruktoru.
mkdir -p src/Service
Oficiální Symfony dokumentace k service containeru

2. Nech Symfony použít autowiring

  1. Ve výchozím projektu Symfony obvykle automaticky najde třídy v src/ a vytvoří z nich služby.
  2. V konstruktoru napiš konkrétní typ, například LoggerInterface. Container podle typu najde odpovídající objekt a předá ho.
  3. Když existují dvě možné implementace stejného rozhraní, vyber jednu explicitně v services.yaml. Hádání by později bolelo.
php bin/console debug:autowiring LoggerInterface
Oficiální Symfony dokumentace k autowiringu

3. Vstup služby používej přes rozhraní

  1. Tam, kde se může dodavatel změnit, závis na vlastním rozhraní. Například PaymentGateway místo konkrétního SDK klienta.
  2. Konkrétní implementaci vyber v konfiguraci. Aplikační kód pak neví, zda je to ostrá služba, testovací náhrada nebo lokální simulace.
  3. Služba, která má deset závislostí, je signál ke zmenšení odpovědnosti. Neřeš to přidáním jedenácté.
php bin/console debug:container --tag=app.service
Oficiální Symfony dokumentace ke konfiguraci služeb

Krok 4

Ověř propojení dřív, než přidáš další kód

Container umí sám říct, co zná a kam se závislost ztratila.

  1. Najdi svou službu v containeru

    Nahraď App\Service\OrderNumberGenerator názvem své třídy. Vypíše se definice i její argumenty.

    php bin/console debug:container App\Service\OrderNumberGenerator
  2. Zkontroluj typ závislosti

    Příkaz ukáže, které služby Symfony umí předat pro dané rozhraní nebo třídu.

    php bin/console debug:autowiring
  3. Spusť svůj malý test

    V testu předdej jednoduchou náhradu závislosti a ověř výsledek. Právě tady se ukáže výhoda konstruktorové injekce.

    php bin/phpunit

Když to zlobí

Nejčastější chyby

Cannot autowire service

Container nezná typ argumentu nebo neví, kterou implementaci zvolit. Zkontroluj namespace, typ v konstruktoru a případně přidej explicitní vazbu rozhraní na implementaci do services.yaml.

php bin/console debug:autowiring
Do služby předáváš celý container

Je to pohodlné jen první den. Vyber konkrétní závislosti a dej je do konstruktoru. Kód pak prozradí, co opravdu potřebuje, a test nebude stavět polovinu aplikace.

Kontroler obsahuje všechnu logiku

Kontroler má přijmout požadavek a vrátit odpověď. Pravidla pro objednávku, výpočet nebo integraci přesuň do malé služby, kterou kontroler jen zavolá.

Změna jedné služby rozbije deset testů

Služba má pravděpodobně příliš mnoho odpovědností nebo závisí na konkrétních implementacích. Rozděl ji podle use-caseů a na hranách používej rozhraní.

Hotovo

Závislosti už nejsou schované.

Dependency Injection ti teď pomáhá udržet třídy malé a čitelné. Stejný princip používej při každé nové službě.

Zavolejte mi

Zavolám vám následující pracovní den mezi 9:00 a 17:00.

Můžete mi také zavolat rovnou.

+420 605 181 728

Nechte mi telefonní číslo a pošlete žádost o zpětné zavolání.

Odesláním souhlasíte se zpracováním údajů pro vyřízení žádosti.