Currently, when creating a new AR instance, some of its attributes will be initialized with the default values specified in the corresponding DB table. For example, if we have a post table defined as:
CREATE TABLE post (…, status INTEGER DEFAULT 1,…),
and we create a post AR object with
$post=new Post;
The $post->status attribute will become 1 automatically.
This has the benefit that we don’t need to explicitly specify the default value for “status” in the Post class.
Moreover, some DBMS support default values using DB expressions that we cannot exploit in PHP.
So should we remove the support for automatically initializing AR attributes with their DB defaults? Doing so will definitely break backward compatibility.
I think there must be a solution without removing this feature from AR. For example search scenario sets default values to empty strings. Or adding optional $castDefaultValues to AR constructor. (not sure how logic that is, didn’t used the filtering and grid-stuff much)
I don’t know how it works, but wouldn’t it be possible to execute such a db expression and then use the returned value as default?
I have not tried it myself, but I don’t see why we can’t combine this with CDbExpression like so :
public function rules()
{
return array(
array('somefield', 'numerical'),
array('fieldthatNeedsDefault', 'default', 'value' => new CDbExpression('NOW()'), 'setOnEmpty' => true),
array('someotherfield', 'required'),
.......
);
}
In theory, this will set your model field to the CDbExpression only if another value was not given. I can vouch that it works with a plain value, and while I haven’t tested it with a CDbExpression, I don’t see why it would not work. It is at least worth a try. Just remember that you have to use validate() on your model to make the rules kick in, but after that you should be good to go!
Using default values from DB feels obscure for me. I always assign default values in the model, as this is more transparent for me and gives a better understanding of what’s going on. As it doesn’t work for all DBMS anyway i consider this feature untrustworthy and would never rely on it. But some users might think that, and could report bugs if not all default values are used. We shouldn’t give “false reliability”
On the other hand i guess, we could still assign default values in the model class and thus override the default values from DB. As long as this is guaranteed, it doesn’t matter for me.
In my opinion, we could have some boolean attribute in the AR that would give the option between loading or not loading default values when creating a new record. Something like
public $loadDefaults = false;
The same for filtering in CGridView, if I want to turn default values on, I should put ‘loadDefaults’ => true in options
Not sure if it is possible or not, but i think that it would be very flexible
Maybe Gii (or a dedicated tool for the upgrade) could "scan" existing models and find out when problems can occur, and eventually update the model adding the default parameters as Orteko suggested.
I think that the method to initialize should be in the core, it’s default implementation is to load the defaults from the db, and called automatically when the model is created, so BC is not a problem…
BUT, this method shoul be overwriten by the code generator in next version of yii (e.g.: 1.4 and +) for each model…
Yes that would be a fix for the (obviously) most common problem.
Or just
$model=new yourmodel("search", false);
false == don’t trigger loading defaults from db
But default values are part of table-scheme, so I think it fits well to AR. Anyone know how RoR handles it?
I don’t know how many guys don’t use gii/code-generation at all, but I’m one of them. I hope we can find better solution here instead of breaking BC.
The problem I see is it can’t be configured globally. Only per model. But still this would be an option since there are not many scenarios were one don’t want to have the default values.
I really like the idea of having Gii set the defaults at model generation.
Would be nice if you could combine that with a toggle to load the defaults or not - if Gii generated with defaults, then have gii generate the toggle set to false, otherwise let the default toggle setting be true (load defaults).