CakePHP是否支持多个模型的交易?

时间:2011-08-29 20:34:30

标签: cakephp transactions cakephp-appmodel

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

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

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

1 个答案:

答案 0 :(得分:5)

是的,确实如此。我在我的应用程序模型中有这个,以简化交易。

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()的事情。交易不限于当前模型或相关模型。适用于任何型号。