Intereting Posts
Как рекурсивно перевести алфавит? Как проверить, содержит ли содержимое строки какой-либо HTML-код? Как запросить переведенный контент при использовании поведения перевода? Класс DomDocument не может получить доступ к domnode Как сохранить изменение разметки, которое я сделал, при переходе с одной страницы на другую? В PHP получает сообщение «Class» PDO «не найден» при попытке подключения к Oracle DB После регистрации woocommerce / wordpress Как получить <img> src с CDATA в RSS? SQL-запрос для включения определенного тега WooCommerce Разделить длинную строку, не используя пробел подсчитать количество строк в mysql? Измените эту функцию js так, чтобы она использовала значение, полученное из db вместо значений, указанных в массиве, для генерации опций Select Методы проверки наличия отношений в Doctrine2 Laravel и AJAX спорадические ошибки 401 в опролле Могут ли не-анонимные функции в PHP использовать ключевое слово 'use'?

Как поместить транзакцию begin-commit в контроллер: cakephp?

Я работаю над контроллером, который обновит несколько таблиц. Я могу назвать свою модель с моего контроллера и внутри функции модели, которую я могу начать и передать свой запрос, он может откатить, если произошла ошибка.

Вот мой пример:

контроллер:

//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 

Так можно ли выполнить фиксацию в контроллере? Я могу сделать это только в модели. Заранее спасибо!

Solutions Collecting From Web of "Как поместить транзакцию begin-commit в контроллер: cakephp?"

Так можно ли выполнить фиксацию в контроллере? Я могу сделать это только в модели.

Да, вы можете выполнить фиксацию или откат из контроллера. Сначала вам нужно получить источник данных с одной из ваших моделей. В коде контроллера просто укажите одну из моделей, которые вы используете (при условии, что они все находятся в одной базе данных):

 $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; } 

Я написал этот код, чтобы проиллюстрировать, как я, хотя о вашей проблеме, хотя я не тестировал.

Более полезные ссылки:

  • Сделки в CakePHP Book
  • О поведении CakePHP
  • Как создать Поведение

Я использовал 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(); }