CTimestampBehavior or beforeSave() not functional when using updateByPk()


I’m using an AR class that utilizes zii.behaviors.CTimestampBehavior for automatic time stamping. I’m using updateByPk() to update a record but when doing so, I noticed that the configured “updated_on” column is not updated.

also, I’ve tried commenting out that behavior and try manually with beforeSave() (and also afterValidate()) and fo some reason both are not even called. I concluded this running a debug session in my IDE and putting breakpoints in those methods. I’ve also put breakpoints in CTimestampBehavior->beforeSave() and verified that in case of editing a record, it is called, while when using updateByPk() - not.

Why is that?

How can I have automatic timestamps on updates as well?


updateByPk() is just a helper method which simply builds a update query and executes it.

You have to get an actual CActiveRecord instance for the full set of features like beforeSave(). So first get the record using findByPk() and then call save() or update().

Thanks for the quick reply.

I resorted to use the update/deleteByPk() since both have a condition which enables me to implement optimistic locking and maintain my data integrity. save(), update() and delete() do not have an option to specify a condition which will enable me to have one, atomic operation of a check and conditioned updated/delete on it.

I still need the conditional operation so I guess I’ll go for using updateByPk() and need to have both CTimestampBehavior usage and manual updated_on timestamping if my base AR class optimistic locking methods are used (which are wrappers around update/deleteByPk())

BTW, in my view, since updateByPk() is run on a fully instantiated object it is not a helper function per-se. If it was static function I would have suspected so.

You can do modify the criteria(-condition) when calling save/delete.

Check out this: http://www.yiiframework.com/forum/index.php/topic/5068-activerecord-and-optimistic-locking/

I see.

Yeah, can’t say I’ve read every post and line there but I based my optimistic locking code on the “popular” post there (and also commented on it myself).

As a staff member, do you know if optimistic locking (or other solutions for concurrency issues) is planned for Yii v2? Concurrency problems will occur sooner or later in any web application with more than trivial traffic. I was quite surprised I found nothing about it in current Yii branch (notice I didn’t find anything doesn’t mean there’s nothing there :) ).

I’m sorry I just remembered there was a good topic in the past and I didn’t check out the latest posts. But I think you missed the post after the popular one? There you can see that it also handles the save() case.

I don’t know if such a feature is planned for Yii 2. To my knowledge there is also no topic in the design discussion forum for Yii 2. It could already be implemented, I have no access to the Yii 2 source so I can’t tell. You may ask qiang directly. But in general I think that such a feature could find it’s way into the core.

In other frameworks you would generally be right, but this isn’t the case with Yii’s CActiveRecord. For technical reasons, the methods that should be “static” are not, they are called from an object. It can be an empty produced with model(). For instance, the ubiquitous find*() methods work like this. So does updateByPk().

// not User::findById(1) as one would expect

$user = User::model()->findById(1);

@François Gannaz: Gotcha. Thanks for the input.

I wasn’t aware that save() uses internally updateByPk() if its an update of a model.

When choosing a design I slightly tend toward leaving save() as is without messing with the internals, meaning overriding updateByPk() that is used by save() (where appropriate). One could do so of course.

I chose instead to implement my own base AR class which all my AR classes extend. In this class I have safelyUpdateByPk() and safelyDeleteByPk() which crafts the needed condition along with the logic of the ‘lock_version’ (based on the suggestion of the other forum thread we both talked about).

I agree that having optimistic locking in v2 would be very nice. Its not such a big thing to incorporate it I think (but my hands on experience with Yii’s internals is very slim). I’ll suggest it (probably in the v2 forum).

Thanks again!