How to put begin-commit transaction in controller: cakephp?

I am working on a controller that will update several tables. I can call my model from my controller and inside the model function, which I can start and send my request, it can roll back if an error occurs.

Here is my example:

Controller:

//update table when update button is clicked if (!empty($this->data)) { if ($this->Item->update($this->data)) { $this->Item->create(); $this->redirect('/sample'); return; } else { $this->set('data', $this->data); } } 

Model:

 function update($data) { $this->begin($this); if(!parent::save($data)) { $this->rollback($this); return false; } $this->commit(); return true; } 

Now it works fine. But I need to make a call to another model in my controller, for example, "$ this →" ANOTHER MODEL HERE "-> update ()". I need to have a rollback if a problem occurs with any model transaction. What I think is to put a commit into my controller after a successful model call.

Like that:

 CONTROLLER PHP: BEGIN TRANSACTION ->CALLS MODEL1 IF(MODEL1 == ERROR){ ROLLBACK } ->CALLS MODEL2 IF(MODEL2 == ERROR){ ROLLBACK } COMMIT WHEN NO PROBLEM IS ENCOUNTERED 

So is it possible to execute commit in the controller? I can do this only in the model. Thanks in advance!

+4
source share
3 answers

So is it possible to execute commit in the controller? I can do this only in the model.

Yes, you can commit or roll back from the controller. First you need to get a data source from one of your models. In the controller code, just refer to one of the models that you use (provided that they are all in the same database):

 $ds = $this->MyModelName->getdatasource(); 

Then you can start, commit and roll back to this data source from the controller.

 $ds->begin(); // do stuff and save data to models if($success) { $ds->commit(); } else { $ds->rollback(); } 

I really have a rollback or commit in more than one place if I perform an action and redirect or complete at some point and redirect. I will just illustrate a simple case.

Transaction processing in the controller makes the most sense to me, because the action of the controller is where the transaction boundaries really exist conceptually. The idea of ​​a transaction naturally covers updates for several models. I do this using postgres as the back-end database with Cake 2.2 and 2.3, and it works fine here. YMMV with other db engines, although I suspect.

+2
source

In future versions of CakePHP, transactions need to be improved, as you can see in this CakePHP Lighthouse ticket .

There are two possible solutions offered there, and I am showing you the third. You can create your own method for saving it and manually make transactions:

 public function saveAndUpdate($data) { $ds = $this->getDataSource(); $ds->begin(); if ($this->save($data)) { foreach(Array('Model1', 'Model2') as $model) { if (!ClassRegistry::init($model)->update()) { $db->rollback(); return false; } } return $db->commit() !== false; } return false; } 

I wrote this code to illustrate how I do, although about your problem, although I have not tested it.

Additional useful links:

0
source

I used commit in my if statements and rollback in my else statements. Since I used two different models inside the controller, I created two different data sources

  $transactiondatasource = $this->Transaction->getDataSource(); $creditcarddatasource = $this->Creditcard->getDataSource(); $transactiondatasource->begin(); $creditcarddatasource->begin(); if (CONDITION){ $creditcarddatasource->commit(); $transactiondatasource->commit(); CakeSession::delete('Cart'); } else { $this->Session->setFlash(__('MESSAGE')); $creditcarddatasource->rollback(); $transactiondatasource->rollback(); } 
-1
source

All Articles