Skip to content

Commit 9374ca0

Browse files
committed
inject injection: improved
1 parent ae73128 commit 9374ca0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+305
-785
lines changed

best-practices/bg/inject-method-attribute.texy

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@
22
********************************
33

44
.[perex]
5-
С помощта на конкретни примери ще разгледаме възможностите за предаване на зависимости на презентатори и ще обясним методите и атрибутите/анотациите на `inject`.
5+
В тази статия ще се съсредоточим върху различните начини за предаване на зависимости на презентатори в рамката Nette. Ще сравним предпочитания метод, който е конструкторът, с други възможности, като например методи и атрибути на `inject`.
6+
7+
И за презентаторите предаването на зависимости чрез [конструктора |dependency-injection:passing-dependencies#Constructor Injection] е предпочитаният начин.
8+
Въпреки това, ако създадете общ предшественик, от който другите презентатори наследяват (например BasePresenter), и този предшественик също има зависимости, възниква проблем, който наричаме [конструкторски ад |dependency-injection:passing-dependencies#Constructor hell].
9+
Той може да бъде заобиколен с помощта на алтернативни методи, които включват инжектиране на методи и атрибути (анотации).
610

711

812
`inject*()` Методи .[#toc-inject-methods]
913
=========================================
1014

11-
В presenter, както и във всеки друг код, предпочитаният начин за предаване на зависимости е чрез използване на [конструктор |dependency-injection:passing-dependencies#Constructor Injection]. Въпреки това, ако presenter наследява от общ предшественик (например `BasePresenter`), по-добре е да се използват методите на `inject*()` в този предшественик. Това е специален случай на setter, при който методът започва с префикс `inject`. Това е така, защото запазваме конструктора свободен за потомците:
15+
Това е форма на предаване на зависимости с помощта на [задаващи елементи |dependency-injection:passing-dependencies#Setter Injection]. Имената на тези задаващи елементи започват с префикса inject.
16+
Nette DI автоматично извиква тези методи веднага след създаването на инстанцията на презентатора и им предава всички необходими зависимости. Следователно те трябва да бъдат декларирани като публични.
17+
18+
`inject*()` Методите могат да се разглеждат като вид разширение на конструктора в множество методи. Благодарение на това `BasePresenter` може да приема зависимости чрез друг метод и да остави конструктора свободен за своите наследници:
1219

1320
```php
1421
abstract class BasePresenter extends Nette\Application\UI\Presenter
@@ -32,55 +39,18 @@ class MyPresenter extends BasePresenter
3239
}
3340
```
3441

35-
Основната разлика от setter е, че Nette DI автоматично извиква методите с тези имена в preenters веднага след създаването на инстанцията, като им предава всички необходими зависимости. Презентаторът може да съдържа няколко метода `inject*()`, като всеки метод може да има произволен брой параметри.
36-
37-
Изпълнението чрез конструктор не се препоръчва за общи предци, тъй като по време на унаследяването трябва да получите зависимостите на всички родителски предци и да ги предадете на `parent::__construct()`:
38-
39-
```php
40-
abstract class BasePresenter extends Nette\Application\UI\Presenter
41-
{
42-
private Foo $foo;
43-
44-
public function __construct(Foo $foo)
45-
{
46-
$this->foo = $foo;
47-
}
48-
}
49-
50-
class MyPresenter extends BasePresenter
51-
{
52-
private Bar $bar;
53-
54-
public function __construct(Foo $foo, Bar $bar)
55-
{
56-
parent::__construct($foo); // това е усложнение
57-
$this->bar = $bar;
58-
}
59-
}
60-
```
61-
62-
Методите `inject*()` са полезни и когато главният файл [се състои от функции |presenter-traits] и всяка от тях изисква своя собствена зависимост.
42+
Презентаторът може да съдържа произволен брой методи `inject*()` и всеки от тях може да има произволен брой параметри. Това е чудесно и за случаите, когато презентаторът е [съставен от черти |presenter-traits] и всяка от тях изисква своя собствена зависимост.
6343

64-
Може да се използва и анотацията `@inject`, но е важно да се помни, че капсулирането е нарушено.
6544

45+
`Inject` Атрибути .[#toc-inject-attributes]
46+
===========================================
6647

67-
Анотации `Inject` .[#toc-inject-annotations]
68-
============================================
69-
70-
В този случай свойството е анотирано като `@inject` в коментара към документацията. Типът може да бъде анотиран и в коментара на документацията, ако използвате PHP под версия 7.4.
71-
72-
```php
73-
class MyPresenter extends Nette\Application\UI\Presenter
74-
{
75-
/** @inject */
76-
public Cache $cache;
77-
}
78-
```
48+
Това е форма на [инжектиране в свойствата |dependency-injection:passing-dependencies#Property Injection]. Достатъчно е да посочите кои свойства трябва да бъдат инжектирани и Nette DI автоматично предава зависимостите веднага след създаването на инстанцията на презентатора. За да ги вмъкнете, е необходимо да ги декларирате като публични.
7949

80-
От версия PHP 8.0 свойството може да бъде маркирано с атрибута `Inject`:
50+
Свойствата се маркират с атрибут: (преди се използваше анотацията `/** @inject */`)
8151

8252
```php
83-
use Nette\DI\Attributes\Inject;
53+
use Nette\DI\Attributes\Inject; // вносът е важен тук
8454

8555
class MyPresenter extends Nette\Application\UI\Presenter
8656
{
@@ -89,9 +59,9 @@ class MyPresenter extends Nette\Application\UI\Presenter
8959
}
9060
```
9161

92-
Отново, Nette DI автоматично ще предава зависимости на свойствата, анотирани по този начин в презентатора, веднага щом инстанцията бъде създадена.
62+
Предимството на този метод за предаване на зависимостите е, че той е много икономичен за записване. С въвеждането на [промоцията на свойствата на конструктора |https://blog.nette.org/bg/php-8-0-p-len-pregled-na-novostite#toc-constructor-property-promotion] обаче използването на конструктора изглежда по-лесно.
9363

94-
Този метод има същите недостатъци като предаването на зависимости към публично свойство. Използва се в презентаторите, защото не усложнява кода и изисква минимално въвеждане.
64+
От друга страна, този метод страда от същите недостатъци като предаването на зависимости в свойства като цяло: нямаме контрол върху промените в променливата, а в същото време променливата става част от публичния интерфейс на класа, което е нежелателно.
9565

9666

9767
{{sitename: Най-добри практики}}

best-practices/cs/inject-method-attribute.texy

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@ Metody a atributy inject
22
************************
33

44
.[perex]
5-
Na konkrétních případech si přiblížíme možnosti předávání závislostí do presenterů a vysvětlíme si metody a atributy/anotace `inject`.
5+
V tomto článku se zaměříme na různé způsoby předávání závislostí do presenterů v Nette frameworku. Porovnáme preferovaný způsob, kterým je konstruktor, s dalšími možnostmi, jako jsou metody a atributy `inject`.
6+
7+
I pro presentery platí, že předání závislostí pomocí [konstruktoru |dependency-injection:passing-dependencies#Předávání konstruktorem] je preferovaná cesta.
8+
Pokud ale vytváříte společného předka, od kterého dědí ostatní presentery (např. `BasePresenter`), a tento předek má také závislosti, nastane problém, kterému říkáme [constructor hell |dependency-injection:passing-dependencies#Constructor hell].
9+
Ten lze obejít pomocí alternativních cest, které představují metody a atributy (anotace) `inject`.
610

711

812
Metody `inject*()`
913
==================
1014

11-
V presenterech, stejně jako v každém jiném kódu, je preferovaný způsob předávání závislostí pomocí [konstruktoru |dependency-injection:passing-dependencies#Předávání konstruktorem]. Pokud však presenter dědí od společného předka (např. `BasePresenter`), je lepší v tomto předkovi použít metody `inject*()`. Jedná se o zvláštní případ setteru, kdy metoda začíná prefixem `inject`. Jeho použitím si totiž ponecháme konstruktor volný pro potomky:
15+
Jde o formu předávání závislosti [setterem |dependency-injection:passing-dependencies#Předávání setterem]. Název těchto setterů začíná předponou `inject`.
16+
Nette DI takto pojmenované metody automaticky zavolá hned po vytvoření instance presenteru a předá jim všechny požadované závislosti. Musí být tudíž deklarované jako public.
17+
18+
Metody `inject*()` lze považovat za jakési rozšíření konstruktoru do více metod. Díky tomu může `BasePresenter` převzít závislosti přes jinou metodu a ponechat konstruktor volný pro své potomky:
1219

1320
```php
1421
abstract class BasePresenter extends Nette\Application\UI\Presenter
@@ -32,55 +39,18 @@ class MyPresenter extends BasePresenter
3239
}
3340
```
3441

35-
Základní rozdíl od setteru je ten, že Nette DI takto pojmenované metody v presenterech automaticky volá hned po vytvoření instance a předá jim všechny požadované závislosti. Metod `inject*()` může presenter obsahovat více a každá může mít libovolný počet parametrů.
36-
37-
Pokud bychom závislosti předávali předkům skrze jejich konstruktory, museli bychom ve všech potomcích získávat i jejich závislosti a předávat je do `parent::__construct()`, což komplikuje kód:
38-
39-
```php
40-
abstract class BasePresenter extends Nette\Application\UI\Presenter
41-
{
42-
private Foo $foo;
43-
44-
public function __construct(Foo $foo)
45-
{
46-
$this->foo = $foo;
47-
}
48-
}
49-
50-
class MyPresenter extends BasePresenter
51-
{
52-
private Bar $bar;
53-
54-
public function __construct(Foo $foo, Bar $bar)
55-
{
56-
parent::__construct($foo); // tohle je komplikace
57-
$this->bar = $bar;
58-
}
59-
}
60-
```
61-
62-
Metody `inject*()` se hodí také v případech, kdy je presenter [složen z trait |presenter-traits] a každá z nich si vyžádá vlastní závislost.
42+
Metod `inject*()` může presenter obsahovat libovolný počet a každá může mít libovolný počet parametrů. Skvěle se hodí také v případech, kdy je presenter [složen z trait |presenter-traits] a každá z nich si žádá vlastní závislost.
6343

64-
Je také možné použít anotaci `@inject`, je však třeba mít na paměti, že dojde k porušení zapouzdření.
6544

45+
Atributy `Inject`
46+
=================
6647

67-
Anotace `inject`
68-
================
69-
70-
Jedná se o automatické předávání závislosti do veřejné členské proměnné presenteru, která je označená anotací `@inject` v dokumentačním komentáři. Typ závislosti je možné uvést také v dokumentačním komentáři, pokud používáte PHP nižší než 7.4.
71-
72-
```php
73-
class MyPresenter extends Nette\Application\UI\Presenter
74-
{
75-
/** @inject */
76-
public Cache $cache;
77-
}
78-
```
48+
Jde o formu [injektování do property |dependency-injection:passing-dependencies#Nastavením proměnné]. Stačí označit, do kterých proměnných se má injektovat, a Nette DI automaticky předá závislosti hned po vytvoření instance presenteru. Aby je mohl vložit, je nutné je deklarovat jako public.
7949

80-
Od PHP 8.0 lze proměnnou označit pomocí atributu `Inject`:
50+
Properites označíme atributem: (dříve se používala anotace `/** @inject */`)
8151

8252
```php
83-
use Nette\DI\Attributes\Inject;
53+
use Nette\DI\Attributes\Inject; // import je důležitý
8454

8555
class MyPresenter extends Nette\Application\UI\Presenter
8656
{
@@ -89,9 +59,9 @@ class MyPresenter extends Nette\Application\UI\Presenter
8959
}
9060
```
9161

92-
Nette DI opět takto anotovaným proměnným v presenteru automaticky předá závislosti hned po vytvoření instance.
62+
Výhodou tohoto způsobu předávání závislostí byla velice úsporná podoba zápisu. Nicméně s příchodem [constructor property promotion |https://blog.nette.org/cs/php-8-0-kompletni-prehled-novinek#toc-constructor-property-promotion] se jeví snazší použít konstruktor.
9363

94-
Tento způsob má stejné nedostatky, jako předávání závislosti do veřejné proměnné. V presenterech se používá proto, že nekomplikuje kód a vyžaduje jen minimum psaní.
64+
Naopak tento způsob trpí stejnými nedostatky, jako předávání závislosti do properites obecně: nemáme kontrolu nad změnami v proměnné a zároveň se proměnná stává součástí veřejného rozhraní třídy, což je nežádnoucí.
9565

9666

9767
{{sitename: Best Practices}}

0 commit comments

Comments
 (0)