Компонент

Yii-приложения состоят из компонентов–объектов, созданных согласно спецификациям. Компонент (component) — это экземпляр класса CComponent или производного от него. Использование компонента, как правило, включает доступ к его свойствам, а также вызов и обработку его событий. Базовый класс CComponent устанавливает правила, согласно которым определяются свойства и события.

1. Объявление и использование свойства компонента

Свойство компонента схоже с открытой переменной-членом класса (public member variable). Мы можем читать или устанавливать его значение. Например:

$width=$component->textWidth; // получаем значение свойства textWidth
$component->enableCaching=true; // устанавливаем значение свойства enableCaching

Существует два разных способа определения свойства компонента. Первым способом является обычное объявление открытой переменной-члена класса компонента так, как показано ниже:

class Document extends CComponent
{
    public $textWidth;
}

Другим способом является использование геттеров и сеттеров. Это более гибкий подход потому как помимо обычных свойств вы можете объявлять и свойства, доступные только для чтения или только для записи.

class Document extends CComponent
{
    private $_textWidth;
    protected $_completed=false;
 
    public function getTextWidth()
    {
        return $this->_textWidth;
    }
 
    public function setTextWidth($value)
    {
        $this->_textWidth=$value;
    }
 
    public function getTextHeight()
    {
        // вычисляет и возвращает высоту текста
    }
 
    public function setCompleted($value)
    {
        $this->_completed=$value;
    }
}

Компонент выше может быть использован следующим образом:

$document=new Document();
 
// мы можем как писать в, так и читать из textWidth
$document->textWidth=100;
echo $document->textWidth;
 
// значение textHeight мы можем только получать
echo $document->textHeight;
 
// значение completed мы можем только изменять
$document->completed=true;

При чтении свойства, которое не было объявлено публичным членом класса, Yii пытается использовать методы-геттеры, т.е. для textWidth методом-геттером будет getTextWidth. Тоже самое происходит и при изменении свойства, которое не было объявлено публичным членом класса.

Если существует метод-геттер, но метода-сеттера при этом объявлено не было, то свойство компонента можно использовать только для чтения, в противном случае будет вызвано исключение. Обратное верно и для свойств, доступных только для изменения.

Использование методов чтения и записи имеет дополнительное преимущество: при чтении или записи значения свойства могут быть выполнены дополнительные действия (такие как проверка на корректность, вызов события и др.).

Примечание: Есть небольшая разница в определении свойства через методы и через простое объявление переменной. В первом случае имя свойства не чувствительно к регистру, во втором — чувствительно.

2. События компонента

События компонента — это специальные свойства, в качестве значений которых выступают методы (называемые обработчиками событий). Назначение метода событию приведет к тому, что метод будет вызван автоматически при возникновении этого события. Поэтому поведение компонента может быть изменено совершенно отлично от закладываемого при разработке.

Событие компонента объявляется путём создания метода с именем, начинающимся на on. Так же как и имена свойств, заданных через методы чтения и записи, имена событий не чувствительны к регистру. Следующий код объявляет событие onClicked:

public function onClicked($event)
{
    $this->raiseEvent('onClicked', $event);
}

где $event — это экземпляр класса CEvent или производного от него, представляющего параметр события. К событию можно подключить обработчик как показано ниже:

$component->onClicked=$callback;

где $callback — это корректный callback-вызов PHP (см. PHP-функцию call_user_func). Это может быть либо глобальная функция, либо метод класса. В последнем случае вызову должен передаваться массив: array($object,'methodName').

Обработчик события должен быть определён следующим образом:

function methodName($event)
{}

где $event — это параметр, описывающий событие (передаётся методом raiseEvent()). Параметр $event — это экземпляр класса CEvent или его производного. Как минимум, он содержит информацию о том, кто вызвал событие.

Обработчик события может быть анонимной функцией, требующей наличия версии PHP 5.3+. Например,

$component->onClicked=function($event) {}

Если теперь использовать метод onClicked(), то в нём будет вызвано событие onClicked. Назначенный ему обработчик будет запущен автоматически.

Событию могут быть назначены несколько обработчиков. При возникновении события обработчики будут вызваны в порядке их назначения. Если в обработчике необходимо предотвратить вызов последующих обработчиков, необходимо установить $event->handled в true.

3. Поведения компонента

Для компонентов реализован шаблон проектирования mixin, что позволяет присоединить к ним одно или несколько поведений. Поведение — объект, чьи методы «наследуются» компонентом, к которому он присоединён. Под «наследованием» здесь понимается наращивание функционала, а не наследование в классическом смысле. К компоненту можно прикрепить несколько поведений и, таким образом, получить аналог множественного наследования.

Поведения классов должны реализовывать интерфейс IBehavior. Большинство поведений могут быть созданы путём расширения базового класса CBehavior. В случае если поведение необходимо прикрепить к модели, его можно создать на основе класса CModelBehavior или класса CActiveRecordBehavior, которые реализуют дополнительные, специфические для моделей, возможности.

Чтобы использовать поведение, его необходимо прикрепить к компоненту путём вызова метода поведения attach(). После этого мы можем вызывать методы поведения через компонент:

// $name уникально идентифицирует поведения в компоненте
$component->attachBehavior($name,$behavior);
// test() является методом $behavior
$component->test();

К прикреплённому поведению можно обращаться как к обычному свойству компонента. Например, если поведение с именем tree прикреплено к компоненту, мы можем получить ссылку на объект поведения следующим образом:

$behavior=$component->tree;
// эквивалентно выражению:
// $behavior=$component->asa('tree');

Поведение можно временно деактивировать, чтобы его методы и свойства были недоступны через компонент. Например:

$component->disableBehavior($name);
// выражение ниже приведет к вызову исключения
$component->test();
$component->enableBehavior($name);
// здесь все будет работать нормально
$component->test();

В случае когда два поведения, прикреплённые к одному компоненту, имеют методы с одинаковыми именами, преимущество будет иметь метод поведения, прикреплённого раньше.

Использование поведений совместно с событиями даёт дополнительные возможности. Поведение, прикреплённое к компоненту, может назначать некоторые свои методы в качестве обработчиков событий компонента. В этом случае поведение получает возможность следить за ходом работы компонента и даже изменять его.

Свойства поведения также доступны из компонента, к которому оно присоединено. Свойства включают в себя как открытые поля класса поведения, так и его методы чтения/записи (getters/setters). Например, если поведение имеет свойство с именем xyz и привязано к компоненту $a, то мы можем использовать выражение $a->xyz для доступа к этому свойству.

Total 2 comments

#3629 report it
grigori at 2011/04/25 09:20am
CComponent - основа yii

В основе yii лежит базовый класс CComponent. http://www.yiiframework.com/doc/api/1.1/CComponent

Все классы yii - его потомки. Все, что есть в yii - компоненты.

Основные возможности, которые дает CComponent:

  • виртуальные свойства объектов: возможность описать в классе методы getVar()/setVar() и работать с $obj->var. Если getVar() возвращает массив, можно написать $obj->var['offset'].

  • События (удобно использовать в виджетах), тема требует отдельной статьи.

  • Поведения (mixin). Смысл в том, что в объект можно "добавить" методы и поля. Если вызвать $obj->attachBehavior('nomatter',$behaviourObject);, Методы __call и __get объекта $obj будут искать в объекте $behaviourObject методы и поля, которые отсутствуют в $obj. Тут тоже нужна отдельная статья с примерами.

#2111 report it
Nayjest at 2010/11/12 04:54am
Улучшение руководства

Было бы неплохо написть в этом разделе руководства о создании экземпляров компонентов и их конфигурировании через массивы, Yii::createComponent() упомянуть. Тема крайне важна но совсем не освещена.

Leave a comment

Please to leave your comment.