Я работаю над контроллером, который обновит несколько таблиц. Я могу назвать свою модель с моего контроллера и внутри функции модели, которую я могу начать и передать свой запрос, он может откатить, если произошла ошибка.
Вот мой пример:
контроллер:
//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); } }
Модель:
function update($data) { $this->begin($this); if(!parent::save($data)) { $this->rollback($this); return false; } $this->commit(); return true; }
Теперь это прекрасно работает. Но мне нужно сделать вызов другой модели в моем контроллере, например «$ this ->« ДРУГОЙ МОДЕЛЬ ЗДЕСЬ »-> update ()». Мне нужно иметь откат, если проблема возникает с любой транзакцией модели. То, что я думаю, заключается в том, чтобы поместить фиксацию в мой контроллер после успешного вызова модели.
Примерно так:
CONTROLLER PHP: BEGIN TRANSACTION ->CALLS MODEL1 IF(MODEL1 == ERROR){ ROLLBACK } ->CALLS MODEL2 IF(MODEL2 == ERROR){ ROLLBACK } COMMIT WHEN NO PROBLEM IS ENCOUNTERED
Так можно ли выполнить фиксацию в контроллере? Я могу сделать это только в модели. Заранее спасибо!
Так можно ли выполнить фиксацию в контроллере? Я могу сделать это только в модели.
Да, вы можете выполнить фиксацию или откат из контроллера. Сначала вам нужно получить источник данных с одной из ваших моделей. В коде контроллера просто укажите одну из моделей, которые вы используете (при условии, что они все находятся в одной базе данных):
$ds = $this->MyModelName->getdatasource();
Затем вы можете начинать, совершать и откатываться к этому источнику данных из контроллера.
$ds->begin(); // do stuff and save data to models if($success) { $ds->commit(); } else { $ds->rollback(); }
На самом деле у меня есть откат или фиксация более чем в одном месте, если я выполняю действие и перенаправляю или завершаю на каком-то этапе и перенаправляю. Я просто проиллюстрирую простой случай.
Обработка транзакций в контроллере имеет для меня наибольший смысл, поскольку действие контроллера – это то, где границы транзакций действительно существуют концептуально. Идея транзакции, естественно, охватывает обновления для нескольких моделей. Я делаю это, используя postgres в качестве базы данных заднего конца с Cake 2.2 и 2.3, и он отлично работает здесь. YMMV с другими db-двигателями, хотя я подозреваю.
В будущих версиях CakePHP можно улучшить транзакции, как вы можете увидеть в этом билете CakePHP Lighthouse .
Есть два возможных решения, предлагаемые там, и я показываю вам третий. Вы можете создать собственный метод для его сохранения и вручную совершить транзакции:
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; }
Я написал этот код, чтобы проиллюстрировать, как я, хотя о вашей проблеме, хотя я не тестировал.
Более полезные ссылки:
Я использовал commit в моих операторах if и отката в моих инструкциях else. Поскольку я использовал две разные модели внутри контроллера, я создал два разных источника данных
$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(); }