2015-11-14 19 views
4

我目前在封裝PDO交易方面存在問題,以便於使用;事務執行後,沒有發生數據庫更改!我的想法是隻提供需要在PDO事務中執行的參數和可調用事務。受保護的executeTransaction方法定義了PDO事務的封裝,如下所示。而客戶端方法是getNextWidWithLock,它使用executeTransaction方法。我嘗試將事務從關閉中移出,並且工作正常!可能是爲什麼它似乎沒有對數據庫提交更改。在封裝PDO事務中使用閉包不起作用。爲什麼?

class ParentRepository 
    { ... 
     /** 
     * Executes a transaction with logging. 
     * @param [type] $data  data to be passed inside the callable. 
     * @param Callable $transaction function of the procedure 
     * @return [type]    [description] 
     */ 
     protected function executeTransaction(Array $data, Callable $transaction) 
     { 
      $returnVariable = false; 

      try 
      { 
       $this->mySqlConnect->beginTransaction(); 
       $returnVariable = $transaction($data); 
       $this->mySqlConnect->commit(); 
      } 
      catch(\PDOException $e) 
      { 
       $this->mySqlConnect->rollBack(); 
       // Log errors. 
       $dateTime = date("Y-m-d H:i", time()); 
       self::log(sprintf("Error Transaction @ %s" . PHP_EOL, $dateTime)); 
       self::log(sprintf("[Error Message] => %s %s" . PHP_EOL, PHP_EOL, $e->getMessage())); 
       self::log(sprintf("[File] => %s" . PHP_EOL, $e->getFile())); 
       self::log(sprintf("[Line Number] => %s" . PHP_EOL, $e->getLine())); 
       self::log(sprintf("[Back Trace] => %s %s" . PHP_EOL, PHP_EOL, $e->getTraceAsString())); 
       self::log("______________________________________" . PHP_EOL); 
       throw $e; 
      } 

      return $returnVariable; 
     } 

    /** 
     * Reserves wid in the given table with write-locking. 
     * @param [type] $tableName  [description] 
     * @param [type] $branchId  [description] 
     * @param integer $reservedSlots [description] 
     * @return array     returns an array of wids. 
     * The last element must be used in an UPDATE statement while 
     * the rest must be used in an INSERT statement. 
     */ 
     protected function getNextWidWithLock($tableName, $branchId, $reservedSlots = 1) 
     { 
      if ($reservedSlots === 0) 
       return []; 

      $this->executeTransaction(
       [ 
        'tableName' => $tableName, 
        'branchId' => $branchId, 
        'reservedSlots' => $reservedSlots 
       ], 
       function($params) 
       { 
        extract($params); 

        $minimumWid = $branchId . "0000000"; 
        $maximumWid = $branchId . "9999999"; 

        $preparedStatements = array(
         $this->mySqlConnect->prepare("SET @wid_d = 0"), 
         $this->mySqlConnect->prepare("SELECT COALESCE(MAX(`wid`), $minimumWid) INTO @wid_d FROM $tableName 
            WHERE `wid` >= $minimumWid AND `wid` <= $maximumWid FOR UPDATE"), 
         $this->mySqlConnect->prepare("INSERT INTO $tableName(`wid`) 
           VALUES (IF(@wid_d = 0, $minimumWid + 1 , @wid_d + $reservedSlots))") 
        ); 


        foreach ($preparedStatements as $statement) 
         $statement->execute(); 

        $result = $this->mySqlConnect->prepare("SELECT `wid` FROM $tableName WHERE id = " . $this->mySqlConnect->lastInsertId()); 
        $result->execute(); 
        $end = $result->fetchColumn(); 

        $statement = $this->mySqlConnect->prepare("SELECT IF(@wid_d = 0, $minimumWid + 1 , @wid_d + 1)"); 
        $statement->execute(); 
        $begin = $statement->fetchColumn(); 

        return range($begin, $end); 
       } 
      ); 
     } 


    } 

回答

2

您在使用封$這一點,但它是從PHP 5.3

not supporting

你可以寫這樣的事情:

protected function getNextWidWithLock($tableName, $branchId, $reservedSlots = 1) 
    { 
     if ($reservedSlots === 0) 
      return []; 

     $self = $this; 
     $this->executeTransaction(
      [ 
       'tableName' => $tableName, 
       'branchId' => $branchId, 
       'reservedSlots' => $reservedSlots 
      ], 
      function($params) use ($self, $tableName, $branchId, $reservedSlots) 
      { 
       extract($params); 

       $minimumWid = $branchId . "0000000"; 
       $maximumWid = $branchId . "9999999"; 

       $preparedStatements = array(
        $self->mySqlConnect->prepare("SET @wid_d = 0"), 
        $self->mySqlConnect->prepare("SELECT COALESCE(MAX(`wid`), $minimumWid) INTO @wid_d FROM $tableName 
           WHERE `wid` >= $minimumWid AND `wid` <= $maximumWid FOR UPDATE"), 
        $self->mySqlConnect->prepare("INSERT INTO $tableName(`wid`) 
          VALUES (IF(@wid_d = 0, $minimumWid + 1 , @wid_d + $reservedSlots))") 
       ); 


       foreach ($preparedStatements as $statement) 
        $statement->execute(); 

       $result = $self->mySqlConnect->prepare("SELECT `wid` FROM $tableName WHERE id = " . $self->mySqlConnect->lastInsertId()); 
       $result->execute(); 
       $end = $result->fetchColumn(); 

       $statement = $self->mySqlConnect->prepare("SELECT IF(@wid_d = 0, $minimumWid + 1 , @wid_d + 1)"); 
       $statement->execute(); 
       $begin = $statement->fetchColumn(); 

       return range($begin, $end); 
      } 
     ); 
    } 


} 
+0

那麼,應該怎麼辦?我應該將PDO對象作爲參數傳遞給閉包? – Xegara

+0

是的,或者你可以傳遞$ this,就像上面url中的例子。 – mnv

+0

看來,我只是忘了爲getNextWidWithLock方法返回一個值。我嘗試過使用它,它仍然有效。是不是因爲我使用PHP 5.6.3不起作用? – Xegara

相關問題