我正在工作的控制器,将更新几个表。我可以从控制器调用我的模型,在模型函数中,我可以开始并提交我的查询,如果发生错误,它可以回滚。
这是我的例子:
控制器:
//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->" another model HERE"->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作为后端数据库与蛋糕2.2和2.3,它在这里工作得很好。YMMV与其他db引擎,虽然我怀疑。交易将在CakePHP的期货版本中得到增强,正如您在这张CakePHP灯塔票证中所看到的。
那里提出了两种可能的解决方案,我给你看第三种。您可以创建一个自定义方法来保存它,并手动提交事务:
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;
}
我写这段代码是为了说明我是如何看待你的问题的,尽管我没有测试。
更多有用的链接:
- Transactions at CakePHP Book
- 关于CakePHP行为 如何创建行为
我在if语句中使用commit,在else语句中使用rollback。因为我在一个控制器中使用了两个不同的模型,所以我创建了两个不同的数据源
$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();
}