Назначение поведения классу (модели) - (CBehavior и CActiveRecordBehavior)
Primary tabs
здесь я размещу базовый пример, иллюстрирующий решение указанной в заголовке задачи
вот что получилось =):
<?php /* подмешивает специальное действие обновления записи, - данный компонент (CActiveRecordBehavior наследуется через CModelBehavior CBehavior от CComponent) дложен быть сконфигурирован именем поля(любого кроме главного id) - именно по этому полю будут просматриваться уже существующие записи, если запись с таким полем суест, то её содержимое обновиться (каждый раз модель будет создаваться как новая) - если же нет, то просто будет вызван метод save() */ class UpdateBehavior extends CActiveRecordBehavior { /*поле по которому мы будем искать существующие записи его значение передаётся из конфигурационного файла или из метода behaviours()модели которая хочет "научиться" поведению UpdateBehaviour */ public $keyfield; /*определяет допустимость использования некоторых "родных" свойств CActiveRecord*/ private $_allowOwnerMethods = false; public function updateRecord() // непосредственно сам метод обновления { $modelname = get_class($this->getOwner()); // получаем имя модели Yii::log("имя модели = " . $modelname, 'info'); Yii::log("имя ключевого поля = " . $this->keyfield, 'info'); Yii::log("его значение = " . $this->getOwner()->hash, 'info'); $field = $this->keyfield; $model = $modelname::model()->find( $this->keyfield . '=:' . $this->keyfield, // условие - совпадение атрибута array( ':' . $this->keyfield => $this->getOwner()->$field ) ); //$this->_allowOwnerMethods = true; // разрешаем использование save() сами для себя Yii::app()->params['_allowOwnerMethods'] = true; // устанавливаем глобальное значение if ($model) { // если запись была в базе Yii::log("id найденной модели " . $model->id, 'info'); foreach ($model->attributes as $key => $val) { Yii::log("обновляем атрибут " . $key, 'info'); if (isset($this->getOwner()->$key)) $model->$key = $this->getOwner()->$key;// обновляем значение } if (!$this->_allowOwnerMethods) {// если не разрешено Yii::log("использование save запрещено! ", 'info'); } else Yii::log("использование save разрешено ", 'info'); $model->save(); /* валидацию следует провести заранее // (не будем усложнять код пример)*/ } else { $this->getOwner()->save();/*иначе протсо сохраняем новую запись в базу */ } return 1; } /* перехватываем попытку использвать метод save() самой CActiveRecord- и выводим уведомление о том, что для любой обновляемой или вновь создаваемой и сохраняемой записи надо использовать update()*/ public function beforeSave($event) { /*ПРИМЕЧАНИЕ: дело в том, что когда мы вызовём метод save() объекта-генератора в методе updateRecord() данного класса -событие сохранения будет повторно перехвачено данным методом beforeSave() ,а флаг _allowOwnerMethods неизбежно будет иметь значение по умолчанию = false поэтому прежде чем вызвать save() из updateRecord() мы установим глобальную переменную Yii::app()->params['_allowOwnerMethods'] = true; */ if (!isset(Yii::app()->params['_allowOwnerMethods']) || !Yii::app()->params['_allowOwnerMethods']) { // конец условия Yii::log("использование save запрещено! (ИТОГ) ", 'info'); throw new CDbException(Yii::t('yiiext','Не используйте метод CActiveRecord::save()! при подключённом поведении UpdateDEhavior - используйте для любой обновляемой или вновь создаваемой и сохраняемой записи надо использовать updateRecord().')); }else Yii::log("использование save разрешено (ИТОГ) ", 'info'); } }
если мы хотим чтобы вместо save() сохранение модели всегда выполнялось в updateRecord() (и конечно же - чтобы при этом save() можно было использовать ), то нам следует переписать обработчик beforeSave() таким образом:
/*давайте просто "переопределим" метод CActiveRecord::save() для этого - опять же - перехватим событие beforeSave и вызовем наш метод updateRecord() - а чтобы модель не выполнила save() после перехвата - установим её атрибут isValid = false - это прервёт процесс сохранения */ public function beforeSave($event) { /*сначала поднимаем глобальный флаг чтобы не вызвать рекурсию*/ if (!isset(Yii::app()->params['_ActiveRecordSaveMethod'])) {// если флаг не поднят Yii::app()->params['_ActiveRecordSaveMethod'] = true; // поднимаем флаг $this->updateRecord();// вызываем наш метод/сохранения обновления $sender = $event->sender;// получаем объект-генератор события $event->isValid = false; } }
минусом подобной замены является то, что валидация
Или можно завести свойство, значение которого разработчик конфигурирует вручную по-умолчанию, и на основании этого свойства решать - переопределять ли save() или бросать исключение.
маленький пример получения управления объектом-генератором события через метод-обработчик
- Log in to post comments
- 5707 reads