7

複数の測定単位をサポートするアプリケーションを作成しています。まれに、ユーザーが測定システムを変更したい場合、アプリケーション内のすべての単位列を正しい測定システムにスケーリングする乗数を適用するクエリを実行する必要があります。この操作で何か問題が発生した場合にすべてのデータが正常であることを確認するには、トランザクション内でクエリを実行する必要があります。

複数のモデルをカバーするクエリを含むトランザクションを Cake で実行することは可能ですか?

これまでに見つけたのはDataSource::begin/commit/rollback()だけですが、それは単一のモデルに対するクエリのみをサポートしています。

4

1 に答える 1

8

はい、そうです。トランザクションを簡単にするために、アプリモデルにこれを持っています。

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() のようなことを行うことができます。トランザクションは、現在のモデルまたは関連モデルに限定されません。その任意のモデル。

于 2011-08-30T11:19:42.967 に答える