Skip to content

Commit 570660e

Browse files
committed
added docs
1 parent dad71aa commit 570660e

23 files changed

+4597
-2
lines changed

.gitattributes

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
.gitattributes export-ignore
22
.gitignore export-ignore
33
.github export-ignore
4-
.travis.yml export-ignore
5-
ecs.php export-ignore
4+
ncs.* export-ignore
65
phpstan.neon export-ignore
6+
docs/ export-ignore
77
tests/ export-ignore
88

99
*.sh eol=lf

docs/cs/@home.texy

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Dependency Injection
2+
********************
3+
4+
.[perex]
5+
Balíček `nette/di` poskytuje nesmírně pokročilý kompilovaný DI kontejner pro PHP.
6+
7+
- [Co je Dependency Injection? |introduction]
8+
- [Co je DI kontejner? |container]
9+
- [Nette DI Container |nette-container]
10+
- [Konfigurace |configuration]
11+
- [Definování služeb |services]
12+
- [Autowiring |autowiring]
13+
- [Generované továrny |factory]
14+
- [Předávání závislostí |passing-dependencies]
15+
- [Tvorba rozšíření pro Nette DI|extensions]
16+
17+
18+
Instalace:
19+
20+
```shell
21+
composer require nette/di
22+
```
23+
24+
{{composer: nette/di}}

docs/cs/@left-menu.texy

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
3+
Dependency Injection
4+
--------------------
5+
- [Co je DI? |introduction]
6+
- [Co je DI kontejner? |container]
7+
- [Nette DI Container |nette-container]
8+
- [Konfigurace |configuration]
9+
- [Definování služeb |services]
10+
- [Autowiring |autowiring]
11+
- [Generované továrny |factory]
12+
- [Předávání závislostí |passing-dependencies]
13+
- [Tvorba rozšíření pro Nette DI|extensions]

docs/cs/autowiring.texy

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
Autowiring
2+
**********
3+
4+
.[perex]
5+
Autowiring je skvělá vlastnost, která umí automaticky předávat do konstruktoru a dalších metod požadované služby, takže je nemusíme vůbec psát. Ušetří vám spoustu času.
6+
7+
Díky tomu můžeme vynechat naprostou většinu argumentů při psaní definic služeb. Místo:
8+
9+
```neon
10+
services:
11+
articles: Model\ArticleRepository(@database, @cache.storage)
12+
```
13+
14+
Stačí napsat:
15+
16+
```neon
17+
services:
18+
articles: Model\ArticleRepository
19+
```
20+
21+
Autowiring se řídí podle typů, takže aby fungoval, musí být třída `ArticleRepository` definována asi takto:
22+
23+
```php
24+
namespace Model;
25+
26+
class ArticleRepository
27+
{
28+
public function __construct(\PDO $db, \Nette\Caching\Storage $storage)
29+
{}
30+
public function setCacheStorage(\Nette\Caching\IStorage $storage)
31+
}
32+
```
33+
34+
Aby bylo možné použit autowiring, musí pro každý typ být v kontejneru **právě jedna služba**. Pokud by jich bylo víc, autowiring by nevěděl, kterou z nich předat a vyhodil by výjimku:
35+
36+
```neon
37+
services:
38+
mainDb: PDO(%dsn%, %user%, %password%)
39+
tempDb: PDO('sqlite::memory:')
40+
articles: Model\ArticleRepository # VYHODÍ VÝJIMKU, vyhovuje mainDb i tempDb
41+
```
42+
43+
Řešením by bylo buď autowiring obejít a explicitně uvést název služby (tj `articles: Model\ArticleRepository(@mainDb)`). Šikovnější ale je autowirování jedné ze služeb [vypnout|#Vypnutí autowiringu], nebo první službu [upřednostnit|#Preference autowiringu].
44+
45+
46+
Vypnutí autowiringu
47+
-------------------
48+
49+
Autowirování služby můžeme vypnout pomocí volby `autowired: no`:
50+
51+
```neon
52+
services:
53+
mainDb: PDO(%dsn%, %user%, %password%)
54+
55+
tempDb:
56+
create: PDO('sqlite::memory:')
57+
autowired: false # služba tempDb je vyřazena z autowiringu
58+
59+
articles: Model\ArticleRepository # tudíž předá do kontruktoru mainDb
60+
```
61+
62+
Služba `articles` nevyhodí výjimku, že existují dvě vyhovující služby typu `PDO` (tj. `mainDb` a `tempDb`), které lze do konstruktoru předat, protože vidí jen službu `mainDb`.
63+
64+
65+
Preference autowiringu
66+
----------------------
67+
68+
Pokud máme více služeb stejného typu a u jedné z nich uvedeme volbu `autowired`, stává se tato služba preferovanou:
69+
70+
```neon
71+
services:
72+
mainDb:
73+
create: PDO(%dsn%, %user%, %password%)
74+
autowired: PDO # stává se preferovanou
75+
76+
tempDb:
77+
create: PDO('sqlite::memory:')
78+
79+
articles: Model\ArticleRepository
80+
```
81+
82+
Služba `articles` nevyhodí výjimku, že existují dvě vyhovující služby typu `PDO` (tj. `mainDb` a `tempDb`), ale použije preferovanou službu, tedy `mainDb`.
83+
84+
85+
Pole služeb
86+
-----------
87+
88+
Autowiring umí předávat i pole služeb určitého typu. Protože v PHP nelze nativně zapsat typ položek pole, je třeba kromě typu `array` doplnit i phpDoc komentář s typem položky ve tvaru `ClassName[]`:
89+
90+
```php
91+
namespace Model;
92+
93+
class ShipManager
94+
{
95+
/**
96+
* @param Shipper[] $shippers
97+
*/
98+
public function __construct(array $shippers)
99+
{}
100+
}
101+
```
102+
103+
DI kontejner pak automaticky předá pole služeb odpovídajících danému typu. Vynechá služby, které mají vypnutý autowiring.
104+
105+
Pokud nemůžete ovlivnit podobu phpDoc komentáře, můžete předat pole služeb přímo v konfiguraci pomocí [`typed()`|services#Speciální funkce].
106+
107+
108+
Zúžení autowiringu
109+
------------------
110+
111+
Jednotlivým službám lze autowiring zúžit jen na určité třídy nebo rozhraní.
112+
113+
Normálně autowiring službu předá do každého parametru metody, jehož typu služba odpovídá. Zúžení znamená, že stanovíme podmínky, kterým musí typy uvedené u parametrů metod vyhovovat, aby jim byla služba předaná.
114+
115+
Ukážeme si to na příkladu:
116+
117+
```php
118+
class ParentClass
119+
{}
120+
121+
class ChildClass extends ParentClass
122+
{}
123+
124+
class ParentDependent
125+
{
126+
function __construct(ParentClass $obj)
127+
{}
128+
}
129+
130+
class ChildDependent
131+
{
132+
function __construct(ChildClass $obj)
133+
{}
134+
}
135+
```
136+
137+
Pokud bychom je všechny zaregistrovali jako služby, tak by autowiring selhal:
138+
139+
```neon
140+
services:
141+
parent: ParentClass
142+
child: ChildClass
143+
parentDep: ParentDependent # VYHODÍ VÝJIMKU, vyhovují služby parent i child
144+
childDep: ChildDependent # autowiring předá do konstruktoru službu child
145+
```
146+
147+
Služba `parentDep` vyhodí výjimku `Multiple services of type ParentClass found: parent, child`, protože do jejího kontruktoru pasují obě služby `parent` i `child`, a autowiring nemůže rozhodnout, kterou z nich zvolit.
148+
149+
U služby `child` můžeme proto zúžit její autowirování na typ `ChildClass`:
150+
151+
```neon
152+
services:
153+
parent: ParentClass
154+
child:
155+
create: ChildClass
156+
autowired: ChildClass # lze napsat i 'autowired: self'
157+
158+
parentDep: ParentDependent # autowiring předá do konstruktoru službu parent
159+
childDep: ChildDependent # autowiring předá do konstruktoru službu child
160+
```
161+
162+
Nyní se do kontruktoru služby `parentDep` předá služba `parent`, protože teď je to jediný vyhovující objekt. Službu `child` už tam autowiring nepředá. Ano, služba `child` je stále typu `ParentClass`, ale už neplatí zužující podmínka daná pro typ parametru, tj. neplatí, že `ParentClass` *je nadtyp* `ChildClass`.
163+
164+
U služby `child` by bylo možné `autowired: ChildClass` zapsat také jako `autowired: self`, jelikož `self` je zástupné označení pro třídu aktuální služby.
165+
166+
V klíči `autowired` je možné uvést i několik tříd nebo interfaců jako pole:
167+
168+
```neon
169+
autowired: [BarClass, FooInterface]
170+
```
171+
172+
Zkusme příklad doplnit ještě o rozhraní:
173+
174+
```php
175+
interface FooInterface
176+
{}
177+
178+
interface BarInterface
179+
{}
180+
181+
class ParentClass implements FooInterface
182+
{}
183+
184+
class ChildClass extends ParentClass implements BarInterface
185+
{}
186+
187+
class FooDependent
188+
{
189+
function __construct(FooInterface $obj)
190+
{}
191+
}
192+
193+
class BarDependent
194+
{
195+
function __construct(BarInterface $obj)
196+
{}
197+
}
198+
199+
class ParentDependent
200+
{
201+
function __construct(ParentClass $obj)
202+
{}
203+
}
204+
205+
class ChildDependent
206+
{
207+
function __construct(ChildClass $obj)
208+
{}
209+
}
210+
```
211+
212+
Když službu `child` nijak neomezíme, bude pasovat do konstruktorů všech tříd `FooDependent`, `BarDependent`, `ParentDependent` i `ChildDependent` a autowiring ji tam předá.
213+
214+
Pokud její autowiring ale zúžíme na `ChildClass` pomocí `autowired: ChildClass` (nebo `self`), předá ji autowiring pouze do konstruktoru `ChildDependent`, protože vyžaduje argument typu `ChildClass` a platí, že `ChildClass` *je typu* `ChildClass`. Žádný další typ uvedený u dalších parametrů není nadtypem `ChildClass`, takže se služba nepředá.
215+
216+
Pokud jej omezíme na `ParentClass` pomocí `autowired: ParentClass`, předá ji autowiring opět do konstruktoru `ChildDependent` (protože vyžadovaný `ChildClass` je nadtyp `ParentClass` a nově i do konstruktoru `ParentDependent`, protože vyžadovaný typ `ParentClass` je taktéž vyhovující.
217+
218+
Pokud jej omezíme na `FooInterface`, bude stále autowirovaná do `ParentDependent` (vyžadovaný `ParentClass` je nadtyp `FooInterface`) a `ChildDependent`, ale navíc i do konstruktoru `FooDependent`, nikoliv však do `BarDependent`, neboť `BarInterface` není nadtyp `FooInterface`.
219+
220+
```neon
221+
services:
222+
child:
223+
create: ChildClass
224+
autowired: FooInterface
225+
226+
fooDep: FooDependent # autowiring předá do konstruktoru child
227+
barDep: BarDependent # VYHODÍ VÝJIMKU, žádná služba nevyhovuje
228+
parentDep: ParentDependent # autowiring předá do konstruktoru child
229+
childDep: ChildDependent # autowiring předá do konstruktoru child
230+
```
231+
232+
233+
{{composer: nette/di}}

0 commit comments

Comments
 (0)