【问题标题】:Does CakePHP support transactions over multiple models?CakePHP 是否支持跨多个模型的事务?
【发布时间】:2011-08-29 20:34:30
【问题描述】:

我正在编写一个支持多种测量单位的应用程序。在极少数情况下,用户想要更改他们的测量系统,我需要运行一个查询,该查询应用乘数将应用程序中的每个单位列缩放到正确的测量系统。为了确保在此操作中出现问题时所有数据保持正常,我需要在事务中运行查询。

是否可以在 Cake 中执行包含覆盖多个模型的查询的事务?

到目前为止,我发现的只有 DataSource::begin/commit/rollback(),但它只支持针对单个模型的查询。

【问题讨论】:

  • 呃,你是对的。同样的基本问题,显然没有适当的答案来判断。
  • 如果你想要保存几个相关的模型,你可以使用 saveAll() 方法
  • 嗯.. 我很幸运能够在用户帐户的模型下将它们全部链接在一起,但我想在数据库服务器上进行更新(UPDATE SET field = field * 10)而不是而不是提取数据,执行乘法应用程序,然后将结果推回。这迫使我使用 Model::query() 方法,所以 saveAll 出来了。我想知道我是否能够在父模型上启动和停止事务并达到预期的结果。我会检查一下。
  • 好消息——如果它们都属于同一个父模型,则查询序列可以正常工作。现在一切都解决了;只需理清这道题的重复状态即可。

标签: cakephp transactions cakephp-model


【解决方案1】:

是的。我在我的应用模型中使用了此功能,以简化交易。

https://github.com/infinitas/infinitas/blob/dev/Model/AppModel.php#L677

    /**
     * @brief wrapper for transactions
     *
     * Allow you to easily call transactions manually if you need to do saving
     * of lots of data, or just nested relations etc.
     *
     * @code
     *  // start a transaction
     *  $this->transaction();
     *
     *  // rollback if things are wrong (undo)
     *  $this->transaction(false);
     *
     *  // commit the sql if all is good
     *  $this->transaction(true);
     * @endcode
     *
     * @access public
     *
     * @param mixed $action what the command should do
     *
     * @return see the methods for tranasactions in cakephp dbo
     */
    public function transaction($action = null) {
        $this->__dataSource = $this->getDataSource();
        $return = false;
        if($action === null) {
            $return = $this->__dataSource->begin($this);
        } else if($action === true) {
            $return = $this->__dataSource->commit($this);
        } else if($action === false) {
            $return = $this->__dataSource->rollback($this);
        }
        return $return;
    }

那么你可以这样做:

$saved = true;
$this->transaction();
$saved = $saved && $this->save($data);
$saved = $saved && $this->SomeOtherModel->save($data2);
$saved = $saved && $this->AnotherModel->save($data3);

if($saved){
$this->transaction(true);
    return $this->id;
}
$this->transaction(false);
return false;

您还可以执行以下更复杂的操作:

function save1(){

    $saved = true;
    $this->transaction();
    $saved = $saved && $this->save($data);
    $saved = $saved && $this->save2($data);


    if($saved){
        $this->transaction(true);
        return $this->id;
    }

    $this->transaction(false);
    return false;
}

cake 不支持嵌套事务,但你可以伪造它们

// this will use transactions if its called directly, but will allow a calling method to

// create and manage the transaction.

function save2($data){
    $saved = true;
    $transaction = $this->transaction(); // will only be true if not already started
    $saved = $saved && $this->save($data);

    if($transaction){ // if it was started here, finish it
        if($saved){
            $this->transaction(true);
            return true;
        }

        $this->transaction(false);
        return false;
    }

    return $saved; // return just the status so the other model will finish the transaction
}

为了清楚起见,您可以执行 ClassRegistry::init('SomeRandomModel')->save2() 之类的操作。交易不限于当前模型或相关模型。它适用于任何型号。

【讨论】:

  • 嗯,你是对的。我曾认为 DboSource::begin() 函数正在执行一些特定于模型的操作,因为 Dbo 它需要模型作为参数,但显然它实际上并没有将它用于任何事情。 github.com/cakephp/cakephp/blob/1.3/cake/libs/model/datasources/….
  • dbo 中几乎所有的方法和行为都将模型作为第一个参数。我认为调度调用的方法可以做到这一点,因此即使不需要它,你也可以得到它。
  • Cake 实际上在 2.X 中确实支持嵌套事务。见book.cakephp.org/2.0/en/models/…
  • 这实际上非常棒 - 这不应该是标准功能吗?它使蛋糕交易变得更加容易。
猜你喜欢
  • 2011-02-10
  • 2019-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多