コンポーネントモデル
Netteにおける重要な概念はコンポーネントです。ページには視覚的なインタラクティブコンポーネントを挿入し、フォームやすべてのフォーム要素もコンポーネントです。これらすべてのコンポーネントが継承する基本的な2つのクラスは、nette/component-model
パッケージの一部であり、コンポーネントの木構造階層を作成する役割を担っています。
Component
Nette\ComponentModel\Componentは、すべてのコンポーネントの共通の祖先です。コンポーネントの名前を返す
getName()
メソッドと、その親を返す getParent()
メソッドを含みます。両方は
setParent()
メソッドで設定できます –
最初のパラメータは親で、2番目のパラメータはコンポーネントの名前です。
lookup (string $type): ?Component
階層を上方向に検索し、要求されたクラスまたはインターフェースのオブジェクトを見つけます。たとえば、$component->lookup(Nette\Application\UI\Presenter::class)
は、コンポーネントが(数レベルを介してでも)Presenterに接続されている場合、Presenterを返します。
lookupPath (string $type): ?string
いわゆるパスを返します。これは、現在のコンポーネントと検索対象のコンポーネントの間のパスにあるすべてのコンポーネントの名前を結合して作成された文字列です。したがって、たとえば
$component->lookupPath(Nette\Application\UI\Presenter::class)
は、Presenterに対するコンポーネントの一意の識別子を返します。
Container
Nette\ComponentModel\Containerは親コンポーネント、つまり子を含むコンポーネントであり、木構造を形成します。オブジェクトを簡単に追加、取得、削除するためのメソッドを備えています。これは、たとえばフォームや
Control
および Presenter
クラスの祖先です。
getComponent (string $name): ?Component
コンポーネントを返します。未定義の子を取得しようとすると、ファクトリ
createComponent($name)
が呼び出されます。createComponent($name)
メソッドは、現在のコンポーネントで createComponent<コンポーネント名>
メソッドを呼び出し、パラメータとしてコンポーネント名を渡します。作成されたコンポーネントは、その後、現在の子として現在のコンポーネントに追加されます。これらのメソッドをコンポーネントファクトリと呼び、Container
クラスの子孫で実装できます。
getComponents(): array
直接の子を配列として返します。キーにはこれらのコンポーネントの名前が含まれます。注:バージョン3.0.xでは、このメソッドは配列の代わりにイテレータを返し、最初のパラメータはコンポーネントを深く走査するかどうかを指定し、2番目のパラメータは型フィルタを表していました。これらのパラメータは非推奨です。
getComponentTree(): array
すべてのネストされた子コンポーネントを含む完全なコンポーネント階層をインデックス付き配列として取得します。検索は最初に深さ優先で行われます。
祖先の監視
Netteコンポーネントモデルは、ツリーとの非常に動的な作業を可能にします(コンポーネントを削除、移動、追加できます)。したがって、コンポーネントが作成された直後(コンストラクタ内)に親、親の親などがわかっていると頼るのは間違いです。ほとんどの場合、作成時に親はまったくわかりません。
コンポーネントがPresenterツリーに接続されたことをいつ知るにはどうすればよいですか?親の変更を監視するだけでは不十分です。たとえば、親の親がPresenterに接続されている可能性があるためです。メソッドmonitor($type, $attached,
$detached)が役立ちます。各コンポーネントは、任意の数のクラスとインターフェースを監視できます。接続または切断は、コールバック
$attached
または $detached
を呼び出し、監視対象クラスのオブジェクトを渡すことによって通知されます。
よりよく理解するための例:Nette Formsのファイルアップロード用のフォーム要素を表す
UploadControl
クラスは、フォームの enctype
属性を multipart/form-data
に設定する必要があります。しかし、オブジェクトが作成された時点では、どのフォームにも接続されていない可能性があります。では、どの時点でフォームを変更すればよいでしょうか?解決策は簡単です –
コンストラクタで監視を要求します:
class UploadControl extends Nette\Forms\Controls\BaseControl
{
public function __construct($label)
{
$this->monitor(Nette\Forms\Form::class, function ($form): void {
$form->setHtmlAttribute('enctype', 'multipart/form-data');
});
// ...
}
// ...
}
そして、フォームが利用可能になるとすぐに、コールバックが呼び出されます。(以前は、代わりに共通のメソッド
attached
または detached
が使用されていました)。