2

Zend_db_table を使用していますが、Zend Framework が 2 つのトランザクションがアクティブであると不平を言っているため、いくつかの問題が発生しています。

[message:protected] => There is already an active transaction
[string:Exception:private] => 
[code:protected] => 0
[file:protected] => /var/www/vhosts/test.local/private/library/Zend/Db/Adapter/Pdo/Abstract.php
[line:protected] => 305
[trace:Exception:private] => Array

これは、コントローラーのコードです。

     public function convertAction()
{
    $this->setNoRender();

    // If the quote is a copy of a previous one, fetch all the datas
    $quoteId = Zend_Filter::filterStatic($this->getRequest()->getParam('qte_id'), 'int');
    $quoteTable = new Model_QuotesTable();
    $quoteRow = $quoteTable->findById($quoteId);
    if (count($quoteRow)) {
        $clonedId = $quoteRow->convertToJob();
        $this->flashMessageRedirect('Quotation successfully converted', '/jobs/edit/job_id/' . $clonedId);
    } else {
        $this->flashMessageRedirect('Unable to find the quote to be converted', '/quotes');
    }
}

これは、zend_db_table_abstract を拡張する QuotesTableRow でこの関数を呼び出しています。

    public function convertToJob()
{
    $db = $this->_getTable()->getAdapter();
    $db->beginTransaction();

    $jobsTable = new Model_JobsTable();

    try {

        /*
         * Update the status of the old row to match the $status passed into this function
         */
        $this->qte_status = "Accepted";
        $this->save();

        /*
         * Create new row with the same details as above
         */

        $newRow = $jobsTable->createRow();

        $newRow->job_title = $this->qte_title;
        $newRow->job_cus_id = $this->qte_cus_id;
        $newRow->job_enq_id = $this->qte_enq_id;
        $newRow->job_qte_id = $this->qte_id;
        $newRow->job_title = $this->qte_title;
        $newRow->job_description = $this->qte_description;
        $newRow->job_work_location_id = $this->qte_work_location_id;
        $newRow->job_work_category_id = $this->qte_work_category_id;
        $newRow->job_work_type_id = $this->qte_work_type_id;
        $newRow->job_cus_code = $this->qte_cus_code;
        $newRow->job_cus_name = $this->qte_cus_name;
        $newRow->job_wt_ref_code = $this->qte_wt_ref_code;
        $newRow->job_wt_description = $this->qte_wt_description;
        $newRow->job_wl_code = $this->qte_wl_code;
        $newRow->job_wl_description = $this->qte_wl_description;
        $newRow->job_wc_ref_code = $this->qte_wc_ref_code;
        $newRow->job_wc_description = $this->qte_wc_description;
        $newRow->job_qte_title = $this->qte_title;
        $newRow->job_datetime_created = date('Y-m-d H:i:s');

        $newRowId = $newRow->save();

        $db->commit();
        return $newRowId;
    } 
    catch (Exception $e) { 
        $db->rollback(); 

        echo('<pre>');
        print_r($e);
        echo('</pre>');
        exit();

        throw new Exception($e->getMessage());
        return false;
    }
}

さらに、Model_JobsTable() に関連する save() 関数を使用して行にコメントを付けると、スクリプトが機能しているのに対し、他の保存にコメントを付けると同じエラーが返されるため、現在のモデルに関連していないようです。 ().

4

2 に答える 2

6

このエラーは MySQL から返されており、ZF はエラー メッセージのみを通知しています。

同じリクエストで 2 つのトランザクションを開始していますか? これで、このエラー メッセージが表示された理由を説明できます。または、トランザクションの途中で接続が中止され、ロールバックまたは自動コミットされなかった可能性があります。

データベース接続ごとに 1 つのトランザクションのみを開始する必要があります。1 回のリクエストでアクティブなトランザクションを持つために 2 つのモデルが必要な場合は、2 つの別個のデータベース接続を取得する必要があります。

この問題に関しては、Bill Karwin によるこの (素晴らしい) 回答を参照してください。

クエリを実行してSHOW ENGINE InnoDB STATUS;、アクティブなトランザクションのリストを取得できます。開いているトランザクションがあり、PHP/ZF からのアクティブなトランザクションがない場合は、そのトランザクションを閉じてみてください。それ以外の場合は、コードを調べて、同じ要求で 2 つのトランザクションがどのように開始されているかを確認する必要があります。

于 2012-08-02T17:50:01.217 に答える
3

ご回答ありがとうございます。解決策が見つかりました。問題は、save()関数を 2 回使用していたことです。最初のものを で変更するsave()insert()、問題が解決しました:

public function convertToJob()
{

    $db = $this->_getTable()->getAdapter();
    $db->beginTransaction();

    $jobsTable = new Model_JobsTable();

    try {

        /*
         * Create new row with the same details as above
         */

        $data = array(
            'job_cus_id'            =>  $this->qte_cus_id,
            'job_enq_id'            =>  $this->qte_enq_id,
            'job_qte_id'            =>  $this->qte_id,
            'job_title'             =>  $this->qte_title,
            'job_description'       =>  $this->qte_description,
            'job_work_location_id'  =>  $this->qte_work_location_id,
            'job_work_category_id'  =>  $this->qte_work_category_id,
            'job_work_type_id'      =>  $this->qte_work_type_id,
            'job_cus_code'          =>  $this->qte_cus_code,
            'job_cus_name'          =>  $this->qte_cus_name,
            'job_wt_ref_code'       =>  $this->qte_wt_ref_code,
            'job_wt_description'    =>  $this->qte_wt_description,
            'job_wl_code'           =>  $this->qte_wl_code,
            'job_wl_description'    =>  $this->qte_wl_description,
            'job_wc_ref_code'       =>  $this->qte_wc_ref_code,
            'job_wc_description'    =>  $this->qte_wc_description,
            'job_qte_title'         =>  $this->qte_title,
            'job_datetime_created'  =>  date('Y-m-d H:i:s')
        );

        $newRowId = $jobsTable->insert($data);

        /*
         * Update the status of the old row to match the $status passed into this function
         */

        $this->qte_status = "Accepted";
        $this->save();

        $db->commit();

        return $newRowId;
    } 
    catch (Exception $e) {
        throw new Exception($e->getMessage());
        return false;
    }
}
于 2012-08-03T09:18:42.643 に答える