简体   繁体   中英

Active transactions and PHP

Given a PHP class with several functions of the style

public function $op_Data() {
    $command = Yii::app()->db->createCommand("");
    $transaction = Yii::app->db->beginTransaction();

    try {
      //code here
      $transaction->commit()
    } catch (Exception $e) {
      $transaction->rollback();
      return "Operation Failed\n" . $e->getTraceAsString();
    }
}

is it possible to continue usage of the transaction from previous methods after a commit operation is successful or error is returned?

what I mean is, an insert function is called. It checks if a transaction is active, and uses it. If a transaction is not active, it creates one. The same check occurs for all functions that require transaction functionality.

If this functionality exists, does it affect the commit/rollback operations within the particular function?

If you want to execute SQL queries placed in separate methods in a single transaction you can wrap them like this:

$transaction = Yii::app()->db->beginTransaction();
try {
    $instance->insertMethod();
    $instance->updateMethod();
    $instance->deleteMethod();
    // ...more DB methods calls
    $transaction->commit();
}
catch (Exception $e) {
    $transaction->rollback();
}

In this case, however, you have to check in your methods whether transaction has been already created outside. It could be done using CDbConnection 's getCurrentTransaction( ) method someway like this:

public function $op_Data() {
    $command = Yii::app()->db->createCommand("");
    $transaction = Yii::app()->db->getCurrentTransaction();
    if ($transaction !== null) {
        // Transaction already started outside
        $transaction = null;
    }
    else {
        // There is no outer transaction, creating a local one
        $transaction = Yii::app()->db->beginTransaction();
    }

    try {
      //code here
      if ($transaction !== null)
          $transaction->commit()
    } catch (Exception $e) {
      if ($transaction !== null)
          $transaction->rollback();
      return "Operation Failed\n" . $e->getTraceAsString();
    }
}

UPDATE

If preserving the code of existing PHP class is the preferrable way to go you can also look at opportunity to override default implementation of PHP's PDO class. This nested transactions implementation is a skeleton for possible solution. The main idea is to start the only transaction on first call of beginTransaction() and really end the transaction on Nth call of commit() or rollback() , where N - is a count of sequental beginTransaction() calls.

It highly depends on your database engine, but usually once a transaction has been rolled back or committed, you will have to "create" a new one.

A transaction is a "savepoint" within your database engine and should have no impact on your php code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM