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,
// ...
]);
另见
- Cookbook > Database Access & ORM > Associations - Linking Tables Together
- Cookbook > Database Access & ORM > Deleting Data > Cascading Deletes
对于非关联表/非依赖关联
这就是 \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);
我如何修改下面的代码以确保在 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,
// ...
]);
另见
- Cookbook > Database Access & ORM > Associations - Linking Tables Together
- Cookbook > Database Access & ORM > Deleting Data > Cascading Deletes
对于非关联表/非依赖关联
这就是 \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);