Permalink
Browse files

di-configuration: fixed wrong info about autowiring (again!)

  • Loading branch information...
dg committed Jun 12, 2018
1 parent 8970c22 commit 6eb63b69a4c19336fbb4b401476e0638762a4158
Showing with 60 additions and 48 deletions.
  1. +30 −24 cs/di-configuration.texy
  2. +30 −24 en/di-configuration.texy
@@ -385,10 +385,12 @@ services:
\--


Omezený autowiring
Zúžení autowiringu
------------------

Lze také autowiring omezit jen pro určité třídy nebo rozhraní. Ukážeme si to na příkladu:
Jednotlivým službám lze autowiring zúžit jen na určité třídy nebo rozhraní. Služba se pak předá jen do parametrů (např. konstruktoru), jejichž typehint krom toho, že odpovídá typu služby, odpovídá i typům uvedeným v nastavení.

Ukážeme si to na příkladu:

/--php
class ParentClass
@@ -420,45 +422,31 @@ services:
childDep: ChildDependent # autowiring předá do konstruktoru službu child
\--

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.
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.

U služby `child` můžeme omezit její autowirování jen na třídu `ChildClass`, takže nebude předaná tam, kde se očekává `ParentClass`:
U služby `child` můžeme proto zúžit její autowirování na typ `ChildClass`:

/--neon
services:
parent: ParentClass
child:
factory: ChildClass
autowired: ChildClass # lze napsat: autowired: self
autowired: ChildClass # lze napsat i 'autowired: self'

parentDep: ParentDependent # autowiring předá do konstruktoru službu parent
childDep: ChildDependent # autowiring předá do konstruktoru službu child
\--

V případě služby `parentDep` se do konstruktoru předá `parent`, protože teď je to jediný vyhovující objekt kvůli omezení definovaném u služby `child`.
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á. Typehintu, kterým je `ParentClass`, sice služba odpovídá (tj. `child` *je typu* `ParentClass`), a už neplatí, že `ParentClass` *je typu* `ChildClass` (vazba [is_a|php:]).

U služby `child` by bylo možné místo `autowired: ChildClass` zapsat `autowired: self`, jelikož `self` představuje třídu služby.
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.

V klíči `autowired` je možné uvést i několik tříd nebo interfaců jako pole:

/--neon
autowired: [BarClass, FooInterface]
\--

Tím, že autowiring omezíme pro určitý typ, neříkáme, že bude dostupná čistě jen pro tento typ, ale také pro všechny potomky v dědičné hierarchii. Tj. třeba u služby `child` znamená `autowired: ParentClass` totéž, jako `autowired: [ParentClass, ChildClass]`, protože `ChildClass` je potomkem `ParentClass`.

Příklad:

/--neon
services:
child:
factory: ChildClass
autowired: ParentClass

parentDep: ParentDependent # autowiring předá do konstruktoru službu child
childDep: ChildDependent # autowiring předá do konstruktoru službu child
\--

Zkusme příklad doplnit ještě o rozhraní:

/--php
@@ -485,9 +473,27 @@ class BarDependent
function __construct(BarInterface $obj)
{}
}

class ParentDependent
{
function __construct(ParentClass $obj)
{}
}

class ChildDependent
{
function __construct(ChildClass $obj)
{}
}
\--

Když službu `child` omezíme na `FooInterface`, bude autowirovaná do všech služeb kromě `barDep`:
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á.

Pokud její autowiring ale zúžíme na `ChildClass` pomocí `autowired: ChildClass` (nebo `self`), předá ji autowiring pouze do konstruktoru `ChildDependent`, protože jen tento typehint *je typu* `ChildClass`.

Pokud jej omezíme na `ParentClass` pomocí `autowired: ParentClass`, předá ji autowiring navíc i do konstruktoru `ParentDependent`, protože typehint bude taktéž vyhovovat podmínce.

Pokud jej omezíme na `FooInterface`, bude autowirovaná do konstruktoru `FooDependent` a stále i do `ParentDependent` (typehint `ParentClass` *je typu* `FooInterface`) a `ChildDependent`, ale nikoliv `BarDependent`, neboť typehint `BarInterface` *není typu* `FooInterface`.

/--neon
services:
@@ -505,7 +511,7 @@ services:
Preference autowiringu
----------------------

V autowiringu můžeme také určité služby pro určité typy preferovat. Dělá se to stejně, jako když omezujeme autowiring. Omezením se z ní totiž zároveň stává pro tento typ *preferovaná služba*.
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:

/--neon
services:
@@ -519,7 +525,7 @@ services:
articles: Model\ArticleRepository
\--

Proto služba `articles` nevyhodí výjimku, že existují dvě vyhovující služby (tj. `mainDb` a `tempDb`), které lze do konstruktoru předat, ale použije preferovanou službu, tedy `mainDb`.
Proto 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, ale použije preferovanou službu, tedy `mainDb`.


Více konfiguračních souborů
@@ -383,10 +383,12 @@ services:
\--


Limited Autowiring
------------------
Narrowing of Autowiring
-----------------------

For individual services, autowiring can be narrowed down to specific classes or interfaces. The service is then passed to parameters (e.g. in constructor) whose typehint, in addition that matches service type, also matches the types specified in the settings.

Autowiring can also be restricted to specific classes or interfaces. We will show you on the example:
Let's take an example:

/--php
class ParentClass
@@ -420,43 +422,29 @@ services:

The `parentDep` service throws the exception `Multiple services of type ParentClass found: parent, child`, because both `parent` and `child` fit into its constructor and autowiring can not make a decision on which one to choose.

For service `child`, we can limit its autowing to `ChildClass`, so it will not be passed to where `ParentClass` is expected:
For service `child`, we can therefore narrow down its autowiring to `ChildClass`:

/--neon
services:
parent: ParentClass
child:
factory: ChildClass
autowired: ChildClass # alternative: autowired: self
autowired: ChildClass # alternative: 'autowired: self'

parentDep: ParentDependent # THROWS EXCEPTION, the 'child' can not be autowired
childDep: ChildDependent # passes the service 'child' to the constructor
\--

In the case of `parentDep`, the `parent` is passed to the constructor because it is now the only satisfactory object due to the restrictions defined in `child`.
Now `parent` is passed to `parentDep` constructor, as it is the only satisfactory object now. The `child` service is not autowired here anymore. Typehint, which is `ParentClass`, matches the service (ie `child` *is a* `ParentClass`), but it is not true that `ParentClass` *is a* `ChildClass` (see [is_a|php:]).

In the case of `child`, `autowired: ChildClass` could be written as `autowired: self` as the `self` means service type.
In the case of `child`, `autowired: ChildClass` could be written as `autowired: self` as the `self` means current service type.

The `autowired` key can include several classes and interfaces as array:

/--neon
autowired: [BarClass, FooInterface]
\--

By limiting the autowiring for a certain type, we do not say it will be available purely for this type, but also for all descendants in the hierarchy. I.e. for `child` the `autowired: ParentClass` means the same as `autowired: [ParentClass, ChildClass]` because `ChildClass` is a descendant of `ParentClass`.

Example:

/--neon
services:
child:
factory: ChildClass
autowired: ParentClass

parentDep: ParentDependent # passes the service child to the constructor
childDep: ChildDependent # passes the service child to the constructor
\--

Let's try to add interfaces to the example:

/--php
@@ -483,9 +471,27 @@ class BarDependent
function __construct(BarInterface $obj)
{}
}

class ParentDependent
{
function __construct(ParentClass $obj)
{}
}

class ChildDependent
{
function __construct(ChildClass $obj)
{}
}
\--

When service `child` is limited to `FooInterface`, it will be autowired to all services except `barDep`:
When we do not limit the `child` service, it will fit into the constructors of all `FooDependent`, `BarDependent`, `ParentDependent` and `ChildDependent` classes and autowiring will pass it there.

If we narrow `child` service's autowiring down to `ChildClass` with `autowired: ChildClass` (or `self`), autowiring will pass it only to the `ChildDependent` constructor, because only its typehint *is a* `ChildClass`.

If we limit it to `ParentClass` with `autowired: ParentClass`, autowiring will also pass it to the `ParentDependent` constructor, because its typehint will match too.

If we limit it to `FooInterface`, it will be autowired into the `FooDependent` constructor and still in `ParentDependent` (typehint `ParentClass` *is a* `FooInterface`) and `ChildDependent`, but not in `BarDependent`, because the `BarInterface` typehint *is not a* `FooInterface`.

/--neon
services:
@@ -503,7 +509,7 @@ services:
Preferred Autowiring
--------------------

In autowiring, we can also prefer certain services for certain types. This is done in the same way as when we limit autowiring. By limiting it, however, it has also become a *preferred service* for this type.
If we have more services of the same type and one of them has the `autowired` option, this service becomes the preferred one:

/--neon
services:
@@ -517,7 +523,7 @@ services:
articles: Model\ArticleRepository
\--

Therefore, `articles` does not throw the exception that there are two satisfactory services (ie `mainDb` and `tempDb`) that can be passed to the constructor but use the preferred service, `mainDb`.
Therefore, `articles` does not throw the exception that there are two satisfactory services of type `PDO` (ie `mainDb` and `tempDb`) that can be passed to the constructor, but it uses the preferred service `mainDb`.


Multiple Configuration Files

0 comments on commit 6eb63b6

Please sign in to comment.