Skip to content

Commit f23b1d2

Browse files
committed
added docs
1 parent 4799ee6 commit f23b1d2

23 files changed

+4722
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.github export-ignore
44
ncs.* export-ignore
55
phpstan.neon export-ignore
6+
docs/ export-ignore
67
tests/ export-ignore
78

89
*.sh eol=lf

docs/cs/@home.texy

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
21+
Knihovnu stáhnete a nainstalujete pomocí nástroje [Composer|/best-practices/composer]:
22+
23+
```shell
24+
composer require nette/di
25+
```
26+
27+
{{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: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
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+
}
31+
```
32+
33+
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:
34+
35+
```neon
36+
services:
37+
mainDb: PDO(%dsn%, %user%, %password%)
38+
tempDb: PDO('sqlite::memory:')
39+
articles: Model\ArticleRepository # VYHODÍ VÝJIMKU, vyhovuje mainDb i tempDb
40+
```
41+
42+
Ř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].
43+
44+
45+
Vypnutí autowiringu
46+
-------------------
47+
48+
Autowirování služby můžeme vypnout pomocí volby `autowired: no`:
49+
50+
```neon
51+
services:
52+
mainDb: PDO(%dsn%, %user%, %password%)
53+
54+
tempDb:
55+
create: PDO('sqlite::memory:')
56+
autowired: false # služba tempDb je vyřazena z autowiringu
57+
58+
articles: Model\ArticleRepository # tudíž předá do kontruktoru mainDb
59+
```
60+
61+
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`.
62+
63+
.[note]
64+
Konfigurace autowiringu v Nette funguje odlišně než v Symfony, kde volba `autowire: false` říká, že se nemá autowiring používat pro argumenty konstruktoru dané služby.
65+
V Nette se autowiring používá vždy, ať už pro argumenty konstruktoru, nebo kterékoliv jiné metody. Volba `autowired: false` říká, že instance dané služba nemá být pomocí autowiringu nikam předávána.
66+
67+
68+
Preference autowiringu
69+
----------------------
70+
71+
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:
72+
73+
```neon
74+
services:
75+
mainDb:
76+
create: PDO(%dsn%, %user%, %password%)
77+
autowired: PDO # stává se preferovanou
78+
79+
tempDb:
80+
create: PDO('sqlite::memory:')
81+
82+
articles: Model\ArticleRepository
83+
```
84+
85+
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`.
86+
87+
88+
Pole služeb
89+
-----------
90+
91+
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[]`:
92+
93+
```php
94+
namespace Model;
95+
96+
class ShipManager
97+
{
98+
/**
99+
* @param Shipper[] $shippers
100+
*/
101+
public function __construct(array $shippers)
102+
{}
103+
}
104+
```
105+
106+
DI kontejner pak automaticky předá pole služeb odpovídajících danému typu. Vynechá služby, které mají vypnutý autowiring.
107+
108+
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].
109+
110+
111+
Skalární argumenty
112+
------------------
113+
114+
Autowiring umí dosazovat pouze objekty a pole objektů. Skalární argumenty (např. řetězce, čísla, booleany) [zapíšeme v konfiguraci |services#Argumenty].
115+
Alternativnou je vytvořit [settings-objekt |/best-practices/passing-settings-to-presenters], který skalární hodnotu (nebo více hodnot) zapouzdří do podoby objektu, a ten pak lze opět předávat pomocí autowiringu.
116+
117+
```php
118+
class MySettings
119+
{
120+
public function __construct(
121+
// readonly je možné použít od PHP 8.1
122+
public readonly bool $value,
123+
)
124+
{}
125+
}
126+
```
127+
128+
Vytvoříte z něj službu přidáním do konfigurace:
129+
130+
```neon
131+
services:
132+
- MySettings('any value')
133+
```
134+
135+
Všechny třídy si jej poté vyžádají pomocí autowiringu.
136+
137+
138+
Zúžení autowiringu
139+
------------------
140+
141+
Jednotlivým službám lze autowiring zúžit jen na určité třídy nebo rozhraní.
142+
143+
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á.
144+
145+
Ukážeme si to na příkladu:
146+
147+
```php
148+
class ParentClass
149+
{}
150+
151+
class ChildClass extends ParentClass
152+
{}
153+
154+
class ParentDependent
155+
{
156+
function __construct(ParentClass $obj)
157+
{}
158+
}
159+
160+
class ChildDependent
161+
{
162+
function __construct(ChildClass $obj)
163+
{}
164+
}
165+
```
166+
167+
Pokud bychom je všechny zaregistrovali jako služby, tak by autowiring selhal:
168+
169+
```neon
170+
services:
171+
parent: ParentClass
172+
child: ChildClass
173+
parentDep: ParentDependent # VYHODÍ VÝJIMKU, vyhovují služby parent i child
174+
childDep: ChildDependent # autowiring předá do konstruktoru službu child
175+
```
176+
177+
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.
178+
179+
U služby `child` můžeme proto zúžit její autowirování na typ `ChildClass`:
180+
181+
```neon
182+
services:
183+
parent: ParentClass
184+
child:
185+
create: ChildClass
186+
autowired: ChildClass # lze napsat i 'autowired: self'
187+
188+
parentDep: ParentDependent # autowiring předá do konstruktoru službu parent
189+
childDep: ChildDependent # autowiring předá do konstruktoru službu child
190+
```
191+
192+
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`.
193+
194+
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.
195+
196+
V klíči `autowired` je možné uvést i několik tříd nebo interfaců jako pole:
197+
198+
```neon
199+
autowired: [BarClass, FooInterface]
200+
```
201+
202+
Zkusme příklad doplnit ještě o rozhraní:
203+
204+
```php
205+
interface FooInterface
206+
{}
207+
208+
interface BarInterface
209+
{}
210+
211+
class ParentClass implements FooInterface
212+
{}
213+
214+
class ChildClass extends ParentClass implements BarInterface
215+
{}
216+
217+
class FooDependent
218+
{
219+
function __construct(FooInterface $obj)
220+
{}
221+
}
222+
223+
class BarDependent
224+
{
225+
function __construct(BarInterface $obj)
226+
{}
227+
}
228+
229+
class ParentDependent
230+
{
231+
function __construct(ParentClass $obj)
232+
{}
233+
}
234+
235+
class ChildDependent
236+
{
237+
function __construct(ChildClass $obj)
238+
{}
239+
}
240+
```
241+
242+
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á.
243+
244+
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á.
245+
246+
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í.
247+
248+
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`.
249+
250+
```neon
251+
services:
252+
child:
253+
create: ChildClass
254+
autowired: FooInterface
255+
256+
fooDep: FooDependent # autowiring předá do konstruktoru child
257+
barDep: BarDependent # VYHODÍ VÝJIMKU, žádná služba nevyhovuje
258+
parentDep: ParentDependent # autowiring předá do konstruktoru child
259+
childDep: ChildDependent # autowiring předá do konstruktoru child
260+
```
261+
262+
263+
{{composer: nette/di}}

0 commit comments

Comments
 (0)