В этой статье речь пойдет о событиях (events) в yii. Кратко, внятно и с примером. Ничего лишнего, только суть.
В любом высокоуровневым языке программирования мы можем определять действия пользователя и как-то реагировать на них. Пользователь инициирует событие, а мы пишем код, который обрабатывает это событие. Яркий пример – javascript. Например, по событию click, мы меняем цвет текста, по событию hover скрываем кнопку и т.д.
Похожая ситуация и с yii. Мы имеем некоторый набор действий (событий), который совершает фрэймворк и на эти действия мы можем вешать свой код.
Я приведу пример некоторых предопределенных событий в yii.
Предопределенные события в yii
События модели.
beforeValidate() – вызывается до валидации;
afterValidate() – вызывается после валидации;
beforeSave() – вызывается перед сохранением данных;
afterSave() – вызывается после сохранением данных;
beforeDelete() – вызывается перед удалением данных;
afterDelete() – вызывается после удалениея данных;
afterConstruct();
afterFind();
beforeFind();
А вот таких событий как beforeUpdate () и afterUpdate() нет.
События контроллера.
beforeAction() – вызывается до каких-либо действий контрллера;
afterActione() – вызывается после каких-либо действий контрллера;
beforeRender() – вызывается перед отрисовкой вида;
afterRender() – вызывается после отрисовки вида;
Класс CWebUser (с версии 1.1.3)
afterLogin() - Вызывается из CWebUser после логинизации
beforeLogin() - - Вызывается из CWebUser перед логинизацией
afterLogout() - - Вызывается из CWebUser после выхода пользователя
Пример использования.
Допустим, в модели User нам нужно сохранять метку времени, используя php-функцию time(). Для этого описываем событие:
public function beforeSave() {
// если новая запись в таблицу
if ($this->isNewRecord) {
$this->date = time();
}
// обязательно перегружаем родительский метод
return parent::beforeSave();
}
Теперь перед сохранением данных в базу, будет вызываться событие beforeSave() и выполняться нужный нам код. Вданном примере - присваивание полю date значения метки времени, если это новая запись (insert,а не update).
Или представим, что после редирединга вида 'view', нам нужно очисить куки, а перед выполнением действия 'index'- что-то залогировать. Для этого в контроллер добавим:
public function afterRender($view){
// только после вида 'view'
if($view == 'view'){
unset(Yii::app()->request->cookies['option_by_city_value']);
}
return true;
}
public function afterAction($action) {
if ($action->id == 'index') {
// логируем
}
return true;
}
В классе CWebUser вызываем событие afterLogin(), чтобы залогировать выход юзера
public function afterLogin($fromCookie){
parent::afterLogin($fromCookie);
// например логируем, что пользователь такой-то вышел тогда-то
}
Своё событие
Для начала установим последовательность действий:
Объявляем некоторое событие описанием соответствующего метода.
Назначаем событию один или несколько обработчиков.
Событие вызывается компонентом через метод CComponent::raiseEvent.
При вызове события автоматически срабатывают все подписанные на него методы-обработчики.
Приведу самый простой и примитивный пример, какой только можно. Предположим, что мы хотим, чтобы при успешной логинизации юзера, нам приходило письмо с его данными.
В стандартном контроллере SiteController создадим метод onLogin в котором опишем инициализацию события:
public function onLogin($event) {
// вызов события
$this->raiseEvent('onLogin', $event);
}
Теперь нам надо связать событие и обработчик. В обрабочике и будет хранится весь основной код, где мы будем слать себе письмо с данными юзера. Сам код привязки можно поместить в родительский компонент контроллера SiteController.
// onLogin - имя инициализованного события, $this - то что придет в метод onLogin на место $event
CComponent::getEventHandlers('onLogin')->add(
function($this){
echo 'Сработало событие логинизации';
}
);
Теперь нам в нужно вызывать проинициализированный метод onLogin, который в свою очередь внутри себя вызовет одноименное событие. Естественно, вызывать метод onLogin() нужно в том месте, после которого понятно, что авторизация "удалась":
if ($model->validate() && $model->login()) {
// вызов события
$this->onLogin($this);
// труту-ту
}