2

Since there doesn't seem to be any support for optimistic locking in CakePHP, I'm taking a stab at building a behaviour that implements it. After a little research into behaviours, I think I could run a query in the beforeSave event to check that the version field hasn't changed.

However, I'd rather implement the check by changing the update statement's WHERE clause from

WHERE id = ?

to

WHERE id = ? and version = ?

This way I don't have to worry about other requests changing the database record between the time I read the version and the time I execute the update. It also means I can do one database call instead of two.

I can see that the DboSource.update() method supports conditions, but Model.save() never passes any conditions to it.

It seems like I have a couple of options:

  1. Do the check in beforeSave() and live with the fact that it's not bulletproof.
  2. Hack my local copy of CakePHP to check for a conditions key in the options array of Model.save() and pass it along to the DboSource.update() method.

Right now, I'm leaning in favour of the second option, but that means I can't share my behaviour with other users unless they apply my hack to their framework.

Have I missed an easier option?

Community
  • 1
  • 1
Don Kirkby
  • 53,582
  • 27
  • 205
  • 286

2 Answers2

10

When using save() to update a record, Cake expects an id to be present and will update only the record with this id.

What you're looking for is updateAll():

updateAll(array $fields, array $conditions)

Updates many records in a single call. Records to be updated are identified by the $conditions array, and fields to be updated, along with their values, are identified by the $fields array.

For example, to approve all bakers who have been members for over a year, the update call might look something like:

$this_year = date('Y-m-d h:i:s', strtotime('-1 year'));

$this->Baker->updateAll(
    array('Baker.approved' => true),
    array('Baker.created <=' => "$this_year")
);
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
deceze
  • 510,633
  • 85
  • 743
  • 889
  • Thanks for the suggestion, but I know about updateAll(). I'm trying to write a behaviour that lets you keep using all the standard CakePHP patterns that go through the save() command, and just adds optimistic locking on top. – Don Kirkby Sep 28 '09 at 17:00
  • Just to clarify, the save() command currently uses a default condition that just matches the id field. I want to add a second condition that also ensures the version number hasn't changed because of another user updating the same record. – Don Kirkby Sep 28 '09 at 21:09
-1

I went with hacking my local copy of CakePHP. I haven't looked recently to see if the latest versions of CakePHP offer any new options.

Don Kirkby
  • 53,582
  • 27
  • 205
  • 286