コンポーネントモデル

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 が使用されていました)。

バージョン: 3.x