Родитель большинства классов Yii — CComponent позволяет сделать приложение
очень гибким, так как поддерживает события.
Для описания события необходимо в классе-потомке CComponent объявить метод,
имя которого начинается на on
. Например, если объявить метод onRegister
, будет
создано одноимённое событие. Метод одновременно является обработчиком по умолчанию.
Процесс работы с событием можно описать следующим образом:
Для классов моделей вместо использования событий можно перекрывать соответствующие
методы. Это менее затратно и, в большинстве случаев, отлично работает.
Задача — после валидации модели формы UserForm получить значение поля
fullName
(имя-фамилия) из введённых полей firstName
(имя) и lastName
(фамилия).
В классе CModel, являющимся базовым классом для всех моделей, есть метод
CModel::afterValidate(), срабатывающий после успешной проверки формы. Этим можно
воспользоваться, перекрыв метод в нашей модели UserForm
:
class UserForm extends CFormModel {
public $firstName;
public $lastName;
public $fullName;
public function rules(){
return array(
// Имя и фамилию нужно ввести обязательно
array('firstName, lastName', 'required'),
);
}
public function afterValidate(){
// Модель проверена и наполнена.
// Получаем fullName:
$this->fullName = $this->firstName.' '.$this->lastName;
// Передаём эстафетную палочку другим обработчикам
// данного события.
return parent::afterValidate();
}
}
Этот подход широко используется при разработке поведений
и своих моделей Active Record.
Любому объявленному событию можно назначить обработчик. Сделать это можно несколькими
способами.
Для назначения обработчика можно воспользоваться методом CComponent::attachEventHandler().
Метод принимает два параметра: $name
— имя события и $handler
— обработчик события.
В качестве обработчика можно указать:
Анонимную функцию как результат
create_function.
Например:
$component->attachEventHandler('onClick', create_function('$event', 'echo "Клик!";'));
$component->attachEventHandler('onClick', function($event){
echo "Клик!";
});
Note|Примечание: В случае использования
attachEventHandler
обработчик события заносится в список
обработчиков последним.
Обработчик события всегда определяется как function eventHandler($event){…}
,
где $event
является экземпляром класса CEvent. Данный класс содержит всего
два свойства: sender
и handled
. В первом находится объект, вызвавший событие;
второе, путём присваивания ему значения true
, позволяет предотвратить вызов
ещё не выполненных обработчиков события.
Можно назначать обработчики непосредственно событиям:
$component->onClick=$handler;
// или:
$component->onClick->add($handler);
CComponent::getEventHandlers() — очень полезный метод. Он возвращает для переданного
параметром имени события список (объект CList) всех назначенных обработчиков события.
Следующий код полностью повторяет метод attachEventHandler
:
$component->getEventHandlers('onClick')->add($handler);
getEventHandlers
удобно использовать в том случае, если важен порядок вызова
обработчиков. Например, добавить обработчик первым в список можно
следующим образом:
$component->getEventHandlers('onClick')->insertAt(0, $handler);
Удалить определённый обработчик события можно при помощи метода CComponent::detachEventHandler():
$component->detachEventHandler('onClick', $handler);
Также можно получить список CList при помощи CComponent::getEventHandlers() и
уже из него удалить обработчики.
В Yii объявлено довольно большое количество различных событий и все их можно
использовать для выполнения своего кода на определённых этапах работы приложения.
Например, события
CApplication::onBeginRequest() и CApplication::onEndRequest(), вызываемые
соответственно перед началом выполнения приложения и после его выполнения,
можно использовать для сжатия кода страницы (всё-же, делать это лучше
средствами веб-сервера):
Yii::app()->onBeginRequest = function($event){
return ob_start("ob_gzhandler");
};
Yii::app()->onEndRequest = function($event){
return ob_end_flush();
};
Info|Информация: чтобы найти все определённые в Yii события, ищите «
function on
»
в директорииframework
.
Для компонентов Yii есть возможность назначить обработчик события через файл
конфигурации.
Например, назначить обработчик событию CMessageSource::onMissingTranslation(),
вызываемому при отсутствии перевода сообщения через Yii::t(), можно следующим
образом:
main.php
:
…
'components' => array(
…
// Класс компонента messages — CPhpMessageSource
'messages' => array(
'onMissingTranslation' => array('MyEventHandler', 'handleMissingTranslation'),
),
…
)
…
Сам класс будет выглядеть так:
class MyEventHandler {
public static function handleMissingTranslation($event){
// обрабатываем отсутствие перевода
}
}
Примерно так же можно поступить с событиями приложения. Отличие в том, что
используется первый уровень вложенности в массиве конфигурации.
main.php
:
'onBeginRequest' => function($event){
return ob_start();
},
'onEndRequest' => function($event){
$out=ob_get_flush();
file_put_contents($fileName, $out);
return $out;
}
Покажем создание своего события и его вызов на примере.
Задача — отослать почту при добавлении комментария к записи блога.
class Post extends CModel {
function addComment(Comment $comment){
// добавляем в блог новый комментарий
// …
// Создаём экземпляр потомка CEvent
$event = new CModelEvent($this);
// Вызываем событие
$this->onNewComment($event);
return $event->isValid;
}
// описываем событие onNewComment
public function onNewComment($event) {
// Непосредственно вызывать событие принято в его описании.
// Это позволяет использовать данный метод вместо raiseEvent
// во всём остальном коде.
$this->raiseEvent('onNewComment', $event);
}
}
// Класс-оповещатель
// Рассылает почту при различных событиях
class Notifier {
function comment($event){
$post = $event->sender;
foreach($post->comments as $comment){
// отправляем почту каждому подписавшемуся комментатору
}
}
}
Назначаем оповещателя обработчиком:
$postModel = Post::model()->findByPk(10);
$notifier = new Notifier();
$postModel->onNewComment = array($notifier, 'comment');
Теперь при вызове
$postModel->addComment($comment);
будет выполнен метод $notifier->comment
, который оповестит комментаторов о новом
сообщении.
Автор
: Александр Макаров, Sam Dark (rmcreative.ru)Обсуждение и комментарии
: http://yiiframework.ru/forum/viewtopic.php?f=8&t=127