0

Using Transactions in Cakephp

Posted by Guillermo Mansilla on Mar 1, 2010 in Articles, Tutorial

What? Yes, transactions… just like “begin, commit or rollback”

If you don’t know what a transaction is I will explain that to you very short: It is a way to prepare a bunch of queries in your data base and execute ALL of them when you are sure that every thing is ok, imagine that you are the administrator of a Bank, you have received the order to give every customer a 500$ prize, now, imagine that your database has 1 million customers, what if you are executing the query and suddenly while the query  is updating  the record 800.001 there is an employee that accidentally disconnected the database server? FAIL! Well, almost all RDBMS have a feature called Transactions, with them you can make sure you wont have the problem I said before, imagine that all queries are saved in somewhere, after checking everything is ok and you write a commit sentence you will have all the queries executed.

With that said let’s move to Cakephp, We know Cake has validation rules and by default when you perform a Model::save() there is a call to Model::validates() and if validation fails cake will not tell database engine to save anything, We also know there is a Model::saveAll() method that help us to save 2 models related data and if one model does not pass validation rules there is nothing written to the database.

But what if you need to save data from 2 Models that are not related? if you write something like
if ($this->Model1->save() && $this->Model2->save()) {  …. }

You could have this problem: Lets suppose model2 does not pass the validation, then Model1 will write queries to the database and we don’t want that, we want to make sure both models save data only if both of them pass validation rules

I found this article in the bakery http://bakery.cakephp.org/articles/view/transaction-behavior but I noticed in the comments that this only works on Mysql databases because every database engine has its own syntax, that is why cakephp provides many database drivers, I didn’t test it however, you can try it if you want.

Fortunately Cakephp provides a tool to handle this no matter what database engine you are using.

this is how you use it in your controller (you could and should have this code in your Model but I am not going to talk about that now):

$this->User->transactional = true; //enable transactions in this model
$this->User->begin(); //begin the transaction
if ($this->User->save($this->data['User']) && $this->Tec->save($this->data['Tec']) ) {
        //here the "User" data will not be written to database until I call Model::commit()
        $this->User->commit(); //Here I tell cake to execute the queries related to User model
        $this->flash(__('Data have been saved', true), array('action'=>'index'));
} else { //if User model or Tec model fails then User model data will be rolled back
        $this->User->rollback();
}
Note that I use transaction in just 1 model (I could’ve used it in both models ) I did it in that way because when 1 model fails there are not going to be any changes to the database

Tags:

Copyright © 2010 Cakephp For All All rights reserved. Theme by Laptop Geek.