[Solved] Cdefaultvaluevalidator Vs Beforesave

Hi,

I have a post table (model) which has several fields including author and createdDate. Field author and createdDate should be automatically set by the system. My current solution is to override beforeSave method.

However, upon reading this wiki model rules validation, I come up with an idea to use CDefaultValueValidator.




 array('createdDate', 'default', 'setOnEmpty' => true, 'value' => date('Y-m-d H:i:s')),

 array('author', 'default', 'setOnEmpty' => true, 'value' => Yii::app()->user->name),



However, it does not work. field createdDate and author are not yet filled with the default values.

Anyone can help?

Thank you in advance.

Daniel

I have found that the order of rules is important. I figured out that the author and createdDate were included in required validation as well so the error were raised before default validator executed.

My other problem is now with the lastModifiedDate. If I put on the beforeSave(), it would be as simple as checking !$this->isNewRecord. However, i have no idea on how to do as rule.

Anyone have a clue?

What’s about using scenarios?


array('lastModifiedDate', 'default', 'setOnEmpty' => false, 'value' => date('Y-m-d H:i:s'), 'on' => 'update'),

Hi Joblo,

Thank you for your quick replied and valuable suggestion.

Please help me in understanding scenario on rules validation:

  1. If I have scenario ‘update’, I have to do this in actionUpdate



$model = $this->loadModel($id);

$model->scenario = 'update';



  1. How about other validations? I am not quite understand, do other validations that have no ‘on’ scenario will be executed (validated) as well? Compare to if have ‘on’ clause will only validate for that scenario?

Cheers,

Daniel

You do not need to explicitly set the "insert" and "update" scenarios. These are default scenarios set by the Yii framework: if an ActiveRecord was loaded (e.g. findByPK, …) then it has the "update" scenario; if it was created with the new keyword, then it has the "insert" scenario.

Any validation rules without "on", will be tried regardless of the current scenario.

By the way, I have tackled the adding of auditing attributes differently. Yii comes with a CTimestampBehavior. This can be extended to include other audit attributes, such as your "author".

Here is how it looks like in my case, with 2 extra audit attributes:


class AuditBehavior extends CTimestampBehavior

{

    public $createUserAttribute = "createuserid";

    public $updateUserAttribute = "updateuserid";

    

    /* overrule defaults from CTimestampBehavior */

    public $createAttribute = 'createtime';

    public $updateAttribute = 'updatetime';


    public function beforeSave($event) {

        $this->setUpdateOnCreate = true;


        parent::beforeSave($event);


        if (!Yii::app()->user->isGuest) {

            if ($this->getOwner()->getIsNewRecord() && ($this->createUserAttribute !== null)) {

                $this->getOwner()->{$this->createUserAttribute} = Yii::app()->user->id;

            }

            if ((!$this->getOwner()->getIsNewRecord() || $this->setUpdateOnCreate) && ($this->updateUserAttribute !== null)) {

                $this->getOwner()->{$this->updateUserAttribute} = Yii::app()->user->id;

            }

        }

    }

}

Then in your model (or in the base class of your models if you want this audit functionality everywhere), attach the behavior like this:


    public function init() {

        parent::init();


        $this->attachBehavior("Audit", "AuditBehavior");

    }

Thanks a lot Tom. You gave me the better solution.