Avtomatsko napeljevanje
Autowiring je odlična funkcija, ki lahko samodejno posreduje storitve konstruktorju in drugim metodam, tako da nam jih sploh ni treba pisati. S tem prihranimo veliko časa.
Tako lahko pri pisanju definicij storitev preskočimo veliko večino argumentov. Namesto:
napišite:
Zato je treba razred ArticleRepository
opredeliti na naslednji način:
Za uporabo samodejnega napeljevanja mora biti za vsak tip v vsebniku poudarjena samo ena storitev. Če bi jih bilo več, autowiring ne bi vedel, katero naj posreduje, in bi zavrgel izjemo:
Rešitev bi bila, da se izognemo samodejnemu usmerjanju in izrecno navedemo ime storitve (tj.
articles: Model\ArticleRepository(@mainDb)
). Vendar pa je bolj priročno, da onemogočimo samodejno posredovanje ene storitve ali raje prve storitve.
Onemogočeno samodejno napeljevanje
Samodejno ožičenje storitev lahko onemogočite z uporabo možnosti autowired: no
:
Storitev articles
ne vrže izjeme, da obstajata dve ustrezni storitvi tipa PDO
(tj.
mainDb
in tempDb
), ki ju je mogoče posredovati konstruktorju, saj vidi samo storitev
mainDb
.
Konfiguracija samodejnega navajanja v Nette deluje drugače kot v Symfonyju, kjer možnost
autowire: false
pravi, da se samodejno navajanje ne sme uporabljati za argumente konstruktorja storitve. V Nette se
autowiring vedno uporablja, ne glede na to, ali gre za argumente konstruktorja ali katere koli druge metode. Možnost
autowired: false
pravi, da se primerek storitve ne sme nikamor posredovati z uporabo samodejnega vodenja.
Prednostno samodejno vodenje
Če imamo več storitev iste vrste in ima ena od njih možnost autowired
, ta storitev postane prednostna:
Storitev articles
ne vrže izjeme, da obstajata dve ustrezni storitvi PDO
(tj. mainDb
in
tempDb
), temveč uporabi prednostno storitev, tj. mainDb
.
Zbirka storitev
Samodejno napeljevanje lahko posreduje tudi niz storitev določene vrste. Ker PHP ne more nativno zapisati vrste elementov
polja, je treba poleg vrste array
dodati še komentar phpDoc z vrsto elementa, kot je ClassName[]
:
Vsebnik DI nato samodejno posreduje polje storitev, ki ustrezajo dani vrsti. Izpusti storitve, ki imajo izklopljeno samodejno napeljavo.
Vrsta v komentarju je lahko tudi v obliki array<int, Class>
ali list<Class>
. Če ne
morete nadzorovati oblike komentarja phpDoc, lahko posredujete polje storitev neposredno v konfiguraciji z uporabo typed()
.
Skalarni argumenti
Samodejno napeljevanje lahko posreduje samo predmete in polja predmetov. Skalarne argumente (npr. nize, številke, logične vrednosti) zapišite v konfiguracijo. Druga možnost je, da ustvarite objekt settings-object, ki skalarno vrednost (ali več vrednosti) uokviri kot objekt, ki ga lahko nato ponovno posredujete z uporabo autowiringa.
Storitev ustvarite tako, da jo dodate v konfiguracijo:
Vsi razredi jo bodo nato zahtevali prek samodejnega povezovanja.
Oženje samodejnega napeljevanja
Pri posameznih storitvah lahko samodejno napeljavo zožite na določene razrede ali vmesnike.
Običajno samodejno usmerjanje posreduje storitev vsakemu parametru metode, katere tipu ustreza storitev. Oženje pomeni, da določimo pogoje, ki jih morajo tipi, določeni za parametre metod, izpolnjevati, da se jim posreduje storitev.
Poglejmo primer:
Če bi jih vse registrirali kot storitve, bi bila samodejna povezava neuspešna:
Storitev parentDep
vrže izjemo Multiple services of type ParentClass found: parent, child
, ker sta
tako parent
kot child
vključena v njen konstruktor in se samodejna vključitev ne more odločiti,
katero bo izbrala.
Pri storitvi child
lahko torej njeno samodejno vodenje zožimo na ChildClass
:
Storitev parentDep
je zdaj posredovana konstruktorju storitve parentDep
, saj je zdaj edini ustrezni
objekt. Storitev child
ni več posredovana s samodejnim vodenjem. Da, storitev child
je še vedno tipa
ParentClass
, vendar ne velja več pogoj za zožitev, ki je podan za tip parametra, tj. ne drži več, da je
ParentClass
nadtip ChildClass
.
V primeru child
bi lahko autowired: ChildClass
zapisali kot autowired: self
, saj
self
pomeni trenutni tip storitve.
Ključ autowired
lahko vključuje več razredov in vmesnikov kot polje:
Poskusimo v primer dodati vmesnike:
Če storitve child
ne omejimo, se bo prilegala konstruktorjem vseh razredov FooDependent
,
BarDependent
, ParentDependent
in ChildDependent
in jo bo tja posredoval autowiring.
Če pa njegovo autowiring omejimo na ChildClass
z uporabo autowired: ChildClass
(ali
self
), ga autowiring prenese le v konstruktor ChildDependent
, saj zahteva argument tipa
ChildClass
, ChildClass
pa je tipa ChildClass
. Noben tip, ki je naveden za druge
parametre, ni nadmnožica ChildClass
, zato se storitev ne posreduje.
Če jo omejimo na ParentClass
z uporabo autowired: ParentClass
, jo bo samodejno posredovanje spet
posredovalo konstruktorju ChildDependent
(ker je zahtevani tip ChildClass
nadmnožica
ParentClass
) in tudi konstruktorju ParentDependent
, ker je zahtevani tip ParentClass
prav
tako ustrezen.
Če ga omejimo na FooInterface
, se bo še vedno samodejno usmeril na ParentDependent
(zahtevani tip
ParentClass
je nadtip FooInterface
) in ChildDependent
, dodatno pa še na konstruktor
FooDependent
, ne pa na BarDependent
, saj BarInterface
ni nadtip
FooInterface
.