2012-03-06 15 views
1

當我將「PDO :: commit()」方法放入「try」塊時,它不起作用,即使SQL代碼是確定的。在「嘗試」塊中PHP/PDO :: commit不起作用

$conn->dbh->beginTransaction(); 

$stmt = $conn->dbh->prepare('some SQL-code'); 

$stmt->bindValue(...); 

try 
{ 
    $stmt->execute(); 
    $conn->dbh->commit(); 
} 
catch (Exception $e) 
{ 
    $dbh->rollBack(); 
    echo $e->getMessage(); 
} 

但是,如果我把它放在「catch」塊之後,一切正常。

... 
try 
{ 
    $stmt->execute(); 
} 
catch (Exception $e) 
{ 
    $dbh->rollBack(); 
    echo $e->getMessage(); 
} 
$conn->dbh->commit(); 

是,這是一個預期behaviuor爲什麼PDO ::提交()裏面的「嘗試」塊不起作用?

只是想澄清一下,因爲我花了整整兩個小時才找到解決方案,並且我不確定該解決方案是否正確。


下面的代碼:

Class Connection 
{ 
public $dbh; 
private static $instance; 

private function __construct() 
{ 
    $config = parse_ini_file('config.ini'); 
    $dsn = $config['db.dbms'] . ':host=' . $config['db.host'] . 
      ';dbname=' . $config['db.dbname'] . 
      ';port='  . $config['db.port'] . 
      ';connect_timeout=15'; 
    $this->dbh = new PDO($dsn, $config['db.user'], $config['db.password'], array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
    $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
} 

public static function getInstance() 
{ 
    if (!isset(self::$instance)) 
    { 
     $object = __CLASS__; 
     self::$instance = new $object; 
    } 
    return self::$instance; 
} 
} 

Class NestedSet 
{ 
public function insertAsLastChildOf ($parentnode) 
{ 
    $fields = ''; 
    $params = ''; 

    $conn = Connection::getInstance(); 

    $conn->dbh->beginTransaction(); 

    foreach ($this->_modelfields as $field => $type) 
    { 
     $fields .= '`'.$field.'`, '; 
     $params .= ':'.$field.', ';    
    } 

    $stmt = $conn->dbh->prepare('UPDATE `' . $this->_tablename . '` 
          SET `rgt` = `rgt` + 2 
          WHERE `rgt` >= :parentnodergt; 


          UPDATE `' . $this->_tablename . '` 
          SET `lft` = `lft` + 2 
          WHERE `lft` > :parentnodergt; 


          INSERT INTO `' . $this->_tablename . '` 
           (' . $fields . ' 
           `lft`, 
           `rgt`, 
           `level`) 
          SELECT 
           ' . $params . ' 
           `rgt` - 2, 
           `rgt` - 1, 
           `level` + 1          
          FROM `' . $this->_tablename . '` 
          WHERE `id` = :parentnodeid;'); 

    foreach ($this->_modelfields as $field => $type) 
    { 
     $pdoparam = (stripos($type, 'int') === 0) ? PDO::PARAM_INT : PDO::PARAM_STR; 
     $stmt->bindValue(':'.$field.'', $this->$field, $pdoparam); 
    } 

    $stmt->bindValue(':parentnodergt', $parentnode->rgt, PDO::PARAM_INT); 
    $stmt->bindValue(':parentnodeid', $parentnode->id, PDO::PARAM_INT); 

    try 
    { 
     $stmt->execute(); 
     $conn->dbh->commit(); 
    } 
    catch (PDOException $e) 
    { 
     $conn->dbh->rollBack(); 
     echo $e->getMessage() . '<br/> file - ' . __FILE__ . '<br/> line - ' . __LINE__ . '<br/>'; 
    } 

    unset($stmt); 
} 
} 

我試圖重寫代碼,使我有準備每一個語句的查詢。在這種情況下,一切工作正常 - 如果沒有錯誤,我得到代碼執行,並得到一個異常,否則回滾。

下面的代碼

$stmt_1 = $conn->dbh->prepare('UPDATE `' . $this->_tablename . '` 
          SET `rgt` = `rgt` + 2 
          WHERE `rgt` >= :parentnodergt;'); 
    $stmt_1->bindValue(':parentnodergt', $parentnode->rgt, PDO::PARAM_INT); 

    $stmt_2 = $conn->dbh->prepare('UPDATE `' . $this->_tablename . '` 
          SET `lft` = `lft` + 2 
          WHERE `lft` > :parentnodergt;'); 
    $stmt_2->bindValue(':parentnodergt', $parentnode->rgt, PDO::PARAM_INT); 

    $stmt_3 = $conn->dbh->prepare('INSERT INTO `' . $this->_tablename . '` 
           (' . $fields . ' 
           `lft`, 
           `rgt`, 
           `level`) 
          SELECT 
           ' . $params . ' 
           `rgt` - 2, 
           `rgt` - 1, 
           `level` + 1          
          FROM `' . $this->_tablename . '` 
          WHERE `id` = :parentnodeid;'); 

    foreach ($this->_modelfields as $field => $type) 
    { 
     $pdoparam = (stripos($type, 'int') === 0) ? PDO::PARAM_INT : PDO::PARAM_STR; 
     $stmt_3->bindValue(':'.$field.'', $this->$field, $pdoparam); 
    } 

    $stmt_3->bindValue(':parentnodeid', $parentnode->id, PDO::PARAM_INT); 

    try 
    { 
     $stmt_1->execute(); 
     $stmt_2->execute(); 
     $stmt_3->execute(); 
     $conn->dbh->commit(); 
    } 
    catch (PDOException $e) 
    { 
     $conn->dbh->rollBack(); 
     echo $e->getMessage() . '<br/> file - ' . __FILE__ . '<br/> line - ' . __LINE__ . '<br/>'; 
    } 
    unset($stmt); 

這是否意味着PDO ::準備()不應該與多個查詢中使用?

我在問,因爲我在PDO手冊中沒有找到任何有關這方面的內容。

+0

您是否爲您的PDO實例啓用了異常拋出? '$ dbh-> setAttribute(PDO :: ATTR_ERRMODE,PDO :: ERRMODE_EXCEPTION);' – hakre 2012-03-06 17:45:00

+0

是的,我把它放在Connection類(Singleton)的__construct()中:'$ this-> dbh = new PDO(。 ..); $ this-> dbh-> setAttribute(PDO :: ATTR_ERRMODE,PDO :: ERRMODE_EXCEPTION);'如果我在SQL代碼中有錯誤,則會拋出異常。 – Placido 2012-03-06 17:49:01

+0

試圖挑起異常,看看是否真的有效。 – hakre 2012-03-06 17:50:23

回答

1

您的查詢出了問題。它不在t/c塊中工作,因爲​​正在導致錯誤,因此在調用commit()之前拋出異常。在t/c塊之後移動它的唯一原因是因爲這是一個程序性的步驟。嘗試拖尾錯誤日誌。

+0

您可以在初始分配後執行'var_dump($ stmt);'嗎?這些多個查詢語句很混亂,我很好奇它是否可行。 – 2012-03-07 02:00:40

+0

我試圖一次做一個查詢,它的工作原理。在這種情況下,如果查詢中有錯誤,我會拋出異常。例如,如果我只留下INSERT查詢並嘗試爲PK字段創建一個重複條目,我將得到以下異常:SQLSTATE [23000]:完整性約束違規:1062重複條目'5th',用於鍵'引用' file-C :\ ... \類\ NestedSet。php line - 187' – Placido 2012-03-07 06:31:32

+0

當您將它們作爲單獨的語句使用時,您是否在同一事務中擁有它們? – 2012-03-08 00:00:47

相關問題