CakePHP 3.x - 如何在单个事务中从多个表中删除记录?

CakePHP 3.x - How to delete records from multiple tables in a single transaction?

我如何修改下面的代码以确保在 CakePHP 3.x 中两个删除都在一个事务中执行?

// In initialize:
$this->loadModel('A');

// In the delete function: 
$elem=$this->A->get($id);
$rec=$elem->...; 
$this->A->delete($elem);

$this->loadModel('B');
$this->B->deleteAll(['B.rec'=>$rec]);

对于关联表

如果您的表相互关联,您可以使用 dependent 选项来定义关联,其中相关记录将被自动删除。默认情况下,这将在交易中发生。

 $this->hasMany('B', [
     'dependent' => true,
     // ...
 ]);

另见

对于非关联表/非依赖关联

这就是 \Cake\Datasource\ConnectionInterface::transactional() 方法,分别是 \Cake\Database\Connection::begin()commit()rollback() 方法。

使用 transactional() 是更简单的方法,在传递的回调内部完成的所有操作都在事务中 运行。

引自文档:

The transactional method will do the following:

  • Call begin.
  • Call the provided closure.
  • If the closure raises an exception, a rollback will be issued. The original exception will be re-thrown.
  • If the closure returns false, a rollback will be issued.
  • If the closure executes successfully, the transaction will be committed.

Returns

mixed The return value of the callback.

因此,将您的代码包装在回调中,并确保评估 Table::delete() return 值和 return false(如有必要),以便回滚在删除操作失败时发出。

$connection = \Cake\Datasource\ConnectionManager::get('default');
$result = $connection->transactional(function ($connection) use ($id) {
    $elem = $this->A->get($id);
    $rec = $elem->/*...*/;
    if (!$this->A->delete($elem, ['atomic' => false])) {
        return false;
    }

    $this->loadModel('B');
    $this->B->deleteAll(['B.rec' => $rec]);

    return true;
});

请注意,在这种情况下应禁用 atomic 选项,这样 delete() 就不会尝试自行创建交易。

还应注意,如果您的代码需要,手动包装 delete() 内部事务调用将导致 Model.afterDeleteCommit 事件 被触发要触发该事件,那么你必须自己做。

另见

 $this->Model->hasMany('TrModels', [ 'bindingKey' => 'transaction column', 'foreignKey' => 'transaction column', 'joinType' => 'LEFT', 'dependent' => true, 'cascadeCallbacks' => true,]);

          $deleteINQ = $this->Models->get($id);//Parrent id
         $this->Models->delete($deleteINQ);