Nette Documentation Preview

syntax
Модель компонента
*****************

.[perex]
Важным понятием в Nette является компонент. Мы вставляем [визуальные интерактивные компоненты |application:components] на страницы, формы или все их элементы также являются компонентами. Есть два основных класса, от которых наследуются все эти компоненты, они входят в пакет `nette/component-model` и отвечают за создание иерархии дерева компонентов.


Component
=========
[api:Nette\ComponentModel\Component] является общим предком всех компонентов. Он содержит метод `getName()`, возвращающий имя компонента, и метод `getParent()`, возвращающий его родителя. Оба параметра могут быть заданы с помощью метода `setParent()` - первый параметр - родитель, второй - имя компонента.


lookup(string $type): ?Component .[method]
------------------------------------------
Ищет в иерархии объект нужного класса или интерфейса. Например, `$component->lookup(Nette\Application\UI\Presenter::class)` возвращает presenter, если компонент связан с ним, несмотря на несколько уровней.


lookupPath(string $type): ?string .[method]
-------------------------------------------
Возвращает так называемый путь, который представляет собой строку, образованную путем конкатенации имен всех компонентов на пути между текущим компонентом и искомым компонентом. Так, например, `$component->lookupPath(Nette\Application\UI\Presenter::class)` возвращает уникальный идентификатор компонента относительно ведущего.


Container
=========
[api:Nette\ComponentModel\Container] является родительским компонентом, т.е. компонентом, содержащим дочерние компоненты и, таким образом, формирующим древовидную структуру. Он имеет методы для легкого добавления, извлечения и удаления компонентов. Он является предком, например, формы или классов `Control` и `Presenter`.


getComponent(string $name): ?Component .[method]
------------------------------------------------
Возвращает компонент. Попытка вызова неопределенного дочернего компонента приводит к вызову фабрики [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Метод `createComponent($name)` вызывает метод `createComponent<component name>` в текущем компоненте и передает имя компонента в качестве параметра. Созданный компонент затем передается текущему компоненту как его дочерний компонент. Мы называем эти фабрики компонентов, они могут быть реализованы в классах, унаследованных от `Container`.


getComponents(): array .[method]
--------------------------------
Возвращает прямых потомков в виде массива. Ключи содержат имена этих компонентов. Примечание: в версии 3.0.x метод возвращал итератор вместо массива, а его первый параметр указывал, нужно ли выполнять глубокий итерационный просмотр компонентов, а второй представлял собой фильтр типов. Эти параметры устарели.


getComponentTree(): array .[method]{data-version:3.1.0}
-------------------------------------------------------
Возвращает всю иерархию компонентов, включая все вложенные дочерние компоненты, в виде индексированного массива. Поиск идет сначала в глубину.


Мониторинг предков .[#toc-monitoring-of-ancestors]
==================================================

Модель компонентов Nette позволяет очень динамично работать с деревом (мы можем удалять, перемещать, добавлять компоненты), поэтому было бы ошибкой полагаться на то, что после создания компонента родитель, родитель родителя и т.д. известны сразу (в конструкторе). Обычно родитель вообще не известен в момент создания компонента.

Как узнать, когда компонент был добавлен в дерево презентера? Следить за изменением родителя недостаточно, потому что родитель родителя мог быть присоединен, например, к презентеру. В этом может помочь метод [monitor($type, $attached, $detached) |api:Nette\ComponentModel\Component::monitor()]. Каждый компонент может контролировать любое количество классов и интерфейсов. Подключение или отключение объявляется вызовом обратных вызовов `$attached` и `$detached`, соответственно, и передачей объекта контролируемого класса.

Пример: Класс `UploadControl`, представляющий элемент формы для загрузки файлов в Nette Forms, должен установить атрибут формы `enctype` в значение `multipart/form-data`. Но во время создания объекта он не должен быть привязан ни к какой форме. Когда модифицировать форму? Решение простое - создаем запрос на мониторинг в конструкторе:

```php
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` ).


{{leftbar: nette:@menu-topics}}

Модель компонента

Важным понятием в Nette является компонент. Мы вставляем визуальные интерактивные компоненты на страницы, формы или все их элементы также являются компонентами. Есть два основных класса, от которых наследуются все эти компоненты, они входят в пакет nette/component-model и отвечают за создание иерархии дерева компонентов.

Component

Nette\ComponentModel\Component является общим предком всех компонентов. Он содержит метод getName(), возвращающий имя компонента, и метод getParent(), возвращающий его родителя. Оба параметра могут быть заданы с помощью метода setParent() – первый параметр – родитель, второй – имя компонента.

lookup(string $type): ?Component

Ищет в иерархии объект нужного класса или интерфейса. Например, $component->lookup(Nette\Application\UI\Presenter::class) возвращает presenter, если компонент связан с ним, несмотря на несколько уровней.

lookupPath(string $type): ?string

Возвращает так называемый путь, который представляет собой строку, образованную путем конкатенации имен всех компонентов на пути между текущим компонентом и искомым компонентом. Так, например, $component->lookupPath(Nette\Application\UI\Presenter::class) возвращает уникальный идентификатор компонента относительно ведущего.

Container

Nette\ComponentModel\Container является родительским компонентом, т.е. компонентом, содержащим дочерние компоненты и, таким образом, формирующим древовидную структуру. Он имеет методы для легкого добавления, извлечения и удаления компонентов. Он является предком, например, формы или классов Control и Presenter.

getComponent(string $name): ?Component

Возвращает компонент. Попытка вызова неопределенного дочернего компонента приводит к вызову фабрики createComponent($name). Метод createComponent($name) вызывает метод createComponent<component name> в текущем компоненте и передает имя компонента в качестве параметра. Созданный компонент затем передается текущему компоненту как его дочерний компонент. Мы называем эти фабрики компонентов, они могут быть реализованы в классах, унаследованных от Container.

getComponents(): array

Возвращает прямых потомков в виде массива. Ключи содержат имена этих компонентов. Примечание: в версии 3.0.x метод возвращал итератор вместо массива, а его первый параметр указывал, нужно ли выполнять глубокий итерационный просмотр компонентов, а второй представлял собой фильтр типов. Эти параметры устарели.

getComponentTree(): array

Возвращает всю иерархию компонентов, включая все вложенные дочерние компоненты, в виде индексированного массива. Поиск идет сначала в глубину.

Мониторинг предков

Модель компонентов Nette позволяет очень динамично работать с деревом (мы можем удалять, перемещать, добавлять компоненты), поэтому было бы ошибкой полагаться на то, что после создания компонента родитель, родитель родителя и т.д. известны сразу (в конструкторе). Обычно родитель вообще не известен в момент создания компонента.

Как узнать, когда компонент был добавлен в дерево презентера? Следить за изменением родителя недостаточно, потому что родитель родителя мог быть присоединен, например, к презентеру. В этом может помочь метод monitor($type, $attached, $detached). Каждый компонент может контролировать любое количество классов и интерфейсов. Подключение или отключение объявляется вызовом обратных вызовов $attached и $detached, соответственно, и передачей объекта контролируемого класса.

Пример: Класс UploadControl, представляющий элемент формы для загрузки файлов в Nette Forms, должен установить атрибут формы 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 ).