オートワイヤリング
Autowiringは、コンストラクタなどに自動的にサービスを渡すことができる優れた機能で、私たちはサービスを書く必要が全くありません。時間を大幅に節約できます。
これにより、サービス定義を書く際に、大半の引数を省略することができます。代わりに
と書くだけです。
自動配線は型によって駆動されるので、ArticleRepository
クラスは以下のように定義する必要があります。
autowiring を使用するには、コンテナ内の各タイプに対して ただ1つのサービス が必要です。それ以上あると、autowiring はどれを渡せばいいのかわからなくなり、例外を投げ出してしまいます。
解決策としては、autowiring をバイパスしてサービス名を明示的に指定する方法があります
(例:articles: Model\ArticleRepository(@mainDb)
)。しかし、1つのサービス、または最初のサービスの自動配線を無効にする方が便利です。
自動配線を無効にする
autowired: no
オプションを使用することで、サービスの自動配線を無効にすることができます。
articles
サービスはmainDb
サービスしか見ていないので、
コンストラクタに渡すことのできるPDO
タイプの一致するサービスが二つある
(つまりmainDb
とtempDb
) という例外を投げません。
Nette で自動配線を設定すると、Symfony のautowire: false
オプションで自動配線をサービスのコンストラクタ引数に使用しないように指定した場合とは異なる動作をします。
Nette
では、コンストラクタの引数であろうと他のメソッドであろうと、自動配線は常に使用されます。autowired: false
オプションは、自動配線を使ってサービスのインスタンスをどこにも渡してはいけないというものです。
望ましい自動配線
同じタイプのサービスが複数あり、そのうちの1つがautowired
のオプションを持っている場合、そのサービスが優先されます。
articles
サービスは、一致するPDO
サービスが2つある (すなわちmainDb
とtempDb
)という例外を投げず、優先されるサービス、すなわちmainDb
を使用します。
サービスのコレクション
Autowiring は、特定の型のサービスの配列を渡すこともできます。PHP
は配列の項目の型をネイティブに表記することができないので、array
の型に加えて、ClassName[]
のように項目の型を指定した phpDoc
コメントを追加する必要があります。
DI コンテナは、指定した型に対応するサービスの配列を自動的に渡します。DI コンテナは、指定した型に対応するサービスの配列を自動的に渡します。自動配線が無効になっているサービスは省略されます。
コメントの型は、以下の形式も可能である。 array<int, Class>
または
list<Class>
.phpDoc のコメントの形式を制御できない場合は、
サービスの配列を直接渡すこともできます。 typed()
.
スカラー引数
Autowiring は、オブジェクトとオブジェクトの配列のみを渡すことができます。スカラー引数(文字列、数値、ブール値など)は設定に書きます。 代替案としては、スカラー値(または複数の値)をオブジェクトとしてカプセル化したsettings-objectを作成し、それを autowiring を使って再度渡すことができます。
サービスを作成するには,コンフィギュレーションに追加します.
すべてのクラスは自動配線によってそれを要求します。
オートワイヤリングの絞り込み
個々のサービスにおいて、オートワイヤリングは特定のクラスやインターフェースに絞り込むことができます。
通常、自動配線では、サービスが対応する型を持つ各メソッドパラメータにサービスを 渡す。絞り込みとは、メソッドパラメータに指定された型がサービスを渡すために満たすべき条件を指定することである。
例を挙げてみよう。
すべてサービスとして登録すると、自動配線は失敗してしまいます。
parentDep
サービスは例外Multiple services of type ParentClass found: parent, child
を投げます。なぜならparent
とchild
の両方がそのコンストラクタに適合し、autowiring
はどちらを選ぶべきかの判断を下すことができないからです。
したがって、サービスchild
の自動配線はChildClass
に絞られます。
parentDep
サービスは、現在唯一の一致するオブジェクトであるため、parentDep
サービスのコンストラクタに渡されます。child
サービスは自動配線で渡されなくなりました。はい、child
サービスはまだParentClass
型ですが、パラメータ型に与えられた狭義の条件はもはや適用されません。つまり、ParentClass
is a supertype ofChildClass
はもはや真ではありません。
child
の場合,self
は現在のサービスタイプを意味するので,autowired: ChildClass
はautowired: self
と書くことができる.
autowired
のキーには、いくつかのクラスやインターフェイスを配列として含めることができます。
例題にインターフェイスを追加してみましょう。
child
のサービスを制限しない場合、FooDependent
,BarDependent
,ParentDependent
,ChildDependent
のすべてのクラスのコンストラクタに収まり、 autowiring はそこにそれを渡します。
しかし、autowired: ChildClass
(またはself
) を使ってChildClass
に自動配線を絞ると、ChildDependent
のコンストラクタにしか渡らなくなります。これは、ChildClass
型の引数が必要で、ChildClass
型ChildClass
であるためです。他のパラメータに指定された型はChildClass
のスーパーセットではないので、サービスは渡されません。
autowired: ParentClass
を使ってParentClass
に制限すると、autowiring
はChildDependent
コンストラクタに再び渡します (必要な型ChildClass
はParentClass
のスーパーセットなので)。また、必要な型ParentClass
も一致するのでParentDependent
コンストラクタにも渡します。
FooInterface
に限定すると、ParentDependent
(要求される型ParentClass
はFooInterface
の上位型) とChildDependent
にはまだ自動配線されますが、さらにFooDependent
のコンストラクタには渡されますが、BarInterface
はFooInterface
の上位型ではないので、BarDependent
には渡りません。