2015-04-14 4 views
1

В Yii 1.1.16 Observer Design Pattern реализован с использованием события & behaivours (события могут быть разделены между всеми компонентами, которые распространяются CComponents). У меня есть следующие модели:наблюдатель шаблон дизайна в Yii 1.1.16, приложив обработчик событий и растущие события

  1. User.php (смотри ниже)
  2. Work.php (смотри ниже)
  3. Activity.php

я хочу выполнить следующее: позволяет говорить в контроллера по умолчанию:

<?php 
    public function actionExampleWork() 
    { 
    $work = new Work(); 
    $work->description = 'some random description'; 
    $work->created_at = new CDbException('NOW()'); 
    $work->user_id = 1; 

    //$work->attach() INVOKE EVENT that will be handled by all models which listen to this event 

    $work->save(); 
} 
public function actionExampleUser() 
{ 
    $user = new User(); 
    $user->email = '[email protected]'; 
    $user->username = 'example'; 
    $user->password = '123'; 

    //$user->attach(something) invoke Event that should be handled only by Activity model 

    $user-> save(); 
} 

?> 

на самом деле у меня есть пила много примеров Yii делать связанные вещи, но до сих пор никакого успеха на поиск ответа, который подходит это мой потребности :(

  • Разве это возможно в Yii?
  • Как это реализовать?
  • ** Есть ли альтернативы (кроме вызовов метода обработки вручную в действиях контроллера)? **

User.php

<?php class User extends CActiveRecord 
{ 
public function tableName() 
{ 
    //@return string the associated database table name 
}; 

public function rules() 
{ 
    //@return array validation rules for model attributes. 
}; 

public function relations() 
{ 
    return array(
     'works' => [self::HAS_MANY, 'Works', 'user_id'], 
    ); 
} 

public function attributeLabels() 
{ 
    //@return array customized attribute labels (name=>label) 
} 

public function search() 
{ 
    //@return CActiveDataProvider the data provider that can return the models 
    // based on the search/filter conditions. 
} 
public function updateLastActivity($user_id, $activity_type){ 

    $user = $user->model()->findByPk($user_id);//find user 
    $user->activity_type = $activity_type; 
    $user->last_action = new CDbExpression('NOW()');//update DB column 
    $user->save; //save user 

} 
} ?> 

Work.php

<?php 

class Work extends CActiveRecord 
{ 
public function tableName() 
{ 
    //@return string the associated database table name 
} 

public function rules() 
{ 
    //@return array validation rules for model attributes. 
} 

public function relations() 
{ 
    return array(
     'user' => [self::BELONGS_TO, 'User', 'user_id'], 
    ); 
} 

public function attributeLabels() 
{ 
    //@return array customized attribute labels (name=>label) 
} 

public function search() 
{ 
    //@return CActiveDataProvider the data provider that can return the models 
    // based on the search/filter conditions. 
} 


?> 
+0

это должно помочь вам HTTP: // www.yiiframework.com/wiki/44/behaviors-events –

ответ

1

Вам не нужно Observ er для вашего сценария.

Использование встроенных обработчиков событий У класса модели Yii есть несколько встроенных функций, которые вы можете перезаписать в своем классе.

Посмотрите официальную документацию для CActiveRecord для получения дополнительной информации. http://www.yiiframework.com/doc/api/1.1/CActiveRecord ПОДСКАЗКА: Поиск beforeXXXX, afterXXXX, onXXXXX

В качестве примера, здесь мой предварительно сохраняется обработчик для моей модели пользователя.

/** 
* Runs just before the models save method is invoked. It provides a change to 
* ...further prepare the data for saving. The CActiveRecord (parent class) 
* ...beforeSave is called to process any raised events. 
* 
* @param <none> <none> 
* @return boolean the decision to continue the save or not. 
* 
* @access public 
*/ 

public function beforeSave() { 
    // ///////////////////////////////////////////////////////////////////// 
    // Some scenarios only require certain fields to be updated. We handle 
    // ...this separately. 
    // ///////////////////////////////////////////////////////////////////// 
if ($this->scenario == self::SCENARIO_LOGIN) 
{ 
    /** Login scenario */ 
    $this->last_login = new CDbExpression('NOW()'); 
} 

if ($this->scenario == self::SCENARIO_ACTIVATION) 
{ 
    /** Account activation scenario */ 

    if ($this->activation_status == 'activated') 
    { 
     $this->activation_code = ''; 
     $this->status   = 'active'; 
     $this->activation_time = new CDbExpression('NOW()'); 
    } 
} 

if (($this->scenario == self::SCENARIO_CHANGE_PASSWORD) || 
    ($this->scenario == self::SCENARIO_REGISTER) || 
    ($this->scenario == 'insert') || 
    ($this->scenario == 'update') 
    ) 
{ 
    /** Password change scenario */ 

    // ///////////////////////////////////////////////////////////////////// 
    // Encrypt the password. Only do this if the password is set 
    // ///////////////////////////////////////////////////////////////////// 
    if (isset($this->password) && (!empty($this->password))) 
    { 
     $this->password = CPasswordHelper::hashPassword($this->password); 

    } 
} 


/** All other scenarios */ 

// ///////////////////////////////////////////////////////////////////// 
// Set the create time and user for new records 
// ///////////////////////////////////////////////////////////////////// 
if ($this->isNewRecord) { 
    $this->created_time = new CDbExpression('NOW()'); 
    $this->created_by = '1'; // Special case for not logged in user 
    $this->modified_by = '1'; 
} 
else 
{ 
    $this->modified_by = isset(Yii::app()->user->id)?Yii::app()->user->id:1; 
} 

// ///////////////////////////////////////////////////////////////////// 
// The modified log details is set for record creation and update 
// ///////////////////////////////////////////////////////////////////// 
$this->modified_time = new CDbExpression('NOW()'); 

return parent::beforeSave(); 
} 

Обратите внимание, что у меня есть полный доступ к записи перед тем, Спасите не происходит (то есть. Нет доступа к первичному ключу, когда новая запись обрабатывается.

Смотри также для встраиваемой вставки сценариев» 'и' update '.

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

Использование пользовательских событий

Вы можете создавать пользовательские события.

Создать класс события, например. защищенные/компоненты/Newuser.php:

class NewUser extends CModelEvent{ 
    public $userRecord; 
} 

Затем в контроллере

$userModel->attachEventHandler('onNewUser',newuserEventHandler); 

function newuserEventHandler($event){ 
     // Add custom handling code here 
     do_some_things_here($event->new, $event->id); 
    } 

В вашей модели, вы должны поднять это событие

$event=new NewUserEvent; 
// Add custom data to event. 
$event->new=$this->isNewRecord; 
$event->order=$this->id; 
$this->raiseEvent('onNewUser',$event); 
+0

Это делает его более понятным, но тем не менее. Как Yii поймет тот факт, что если была вызвана модель «Событие в пользователе», то она должна выполнять другие методы модели? –

+0

** Проблема в том, что: я хочу вызывать ** глобальное событие ** в модели User.php, которое будет обрабатываться во всех моделях ('Works.php' ...' ExampleModel.php' .. и т. д.), которые имеют конкретный метод (handleGlobalEvent, поднятый из модели User.php), который соответствует этому событию. Все еще запутано :( –

+0

Я не думаю, что модель событий Yii достаточно зрелая, чтобы справиться с этим сценарием. Тем не менее вы можете создавать пользовательские события, но вам нужно вручную поднять события. Вам нужно будет вручную управлять единицей работы. обновил мой ответ, чтобы показать, как создать настраиваемое событие. – crafter