CakePHP(v3.x)、Transactionを用いたデータの保存

トランザクションを用いると、データの保存の途中に処理に失敗した場合、rollbackで差し戻すことができるので、データベースに意図しない変更が加えられるのを防ぐことができます。

公式ドキュメントはこちらです。

今、以下のようにControllerでデータを保存しようとしている時、

public function add()
{
    $user = $this->Users->newEntity();
    if ($this->request->is('post')) {
        $user = $this->Users->patchEntity($user, $this->request->getData());
        if ($this->Users->save($user, ['validate' => 'registration'])) {
            $this->Flash->success(__('You are now registered.'));
        } else {
            $this->Flash->error(__('There were some problems.'));
        }
    }
    $this->set('user', $user);
}

これにトランザクションを書き加えると、

use Cake\Core\Exception\Exception;
use Cake\Datasource\ConnectionManager;

public function add()
{
    $user = $this->Users->newEntity();
    $connection = ConnectionManager::get('default');
    if ($this->request->is('post')) {
        $connection->begin(); // トランザクション開始
        try {
            $user = $this->Users->patchEntity($user, $this->request->getData());
            if ($this->Users->save($user, ['validate' => 'registration'])) {
                $connection->commit(); // 保存に成功したためコミット
                $this->Flash->success(__('You are now registered.'));
                return $this->redirect('/user/' . $user->id);
            }
            $connection->rollback(); // 保存に失敗したためロールバック
            $this->Flash->error(__('There were some problems.'));         
        } catch (\Throwable $e) { // 例外処理
            $connection->rollback();
            $this->Flash->error(__('There were some problems.'));
        }

    }
    $this->set('user', $user);
}

となります。