I'd like to implement some SluggableBehavior functionality, so I've decided to use behaviors as many times before, but I've got some troubles.
When massively assigning attributes in controller, model verifies that they are safe, so my behavior class should add one new field, that can be safely assigned — 'slug' in my case.
I've implemented it in a veeery ugly way and I definetly don't think, that this is good solution, but it works:
When massively assigning attributes in controller, model verifies that they are safe, so my behavior class should add one new field, that can be safely assigned — 'slug' in my case.
I've implemented it in a veeery ugly way and I definetly don't think, that this is good solution, but it works:
class SluggableBehavior extends CActiveRecordBehavior { public $title; private function _extendModel(SluggableModel $model) { foreach ($model->getValidators() as $validator) { /** @var $validator CValidator */ if ($validator instanceof CSafeValidator) { $validator->attributes[] = 'slug'; } } } public function afterFind(CEvent $event) { $this->_extendModel($this->getOwner()); } public function afterConstruct(CEvent $event) { $this->_extendModel($this->getOwner()); } public function beforeValidate(CEvent $event) { /** @var $owner SluggableModel */ $owner = $this->getOwner(); /** @var $existing SluggableModel */ $existing = $owner->model()->findByAttributes(array( 'slug' => $owner->slug, )); if ($existing !== null && $existing->id != $owner->id) { $owner->addError('slug', 'This field should be unique (now assigned to «' . $existing->{$this->title} . '», ID=' . $existing->id . ').'); } return true; } }