2012-03-06 3 views
1

"PDO :: commit()"메소드를 "try"블록에 넣으면 작동하지 않고 "commit"을 얻지도 않습니다. SQL- 코드는 괜찮습니다.PHP/PDO :: commit이 "try"블록에서 작동하지 않습니다.

$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(); 

이것은 예상되는 동작이며 PDO :: commit()이 "try"블록에서 작동하지 않는 이유는 무엇입니까?

이 문제에 대한 해결책을 찾기 위해 전체 2 시간을 소비했기 때문에 자신을 명확히하고 싶습니다. 솔루션이 올바른지 확실하지 않습니다. 나는 준비된 문장 당 하나 개의 쿼리를 가질 수 있도록 코드를 다시 작성하려고했습니다

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); 
} 
} 

:


여기에 코드입니다. 그 경우에는 모든 것이 잘 작동합니다. 오류가없고 예외가 발생하면 코드가 실행되고 그렇지 않으면 롤백됩니다.

다음은이 PDO는 ::) (준비 여러 쿼리와 함께 사용되어서는 안된다는 뜻 코드

$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 매뉴얼에서 그 사실을 발견하지 못했기 때문에 묻습니다.

+0

PDO 인스턴스의 예외 처리를 활성화 했습니까? – hakre

+0

예, Connection 클래스 (Singleton)의 __construct()에 다음과 같이 입력했습니다 :'$ this-> dbh = new PDO (. ..); $ this-> dbh-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); 그리고 SQL 코드에 오류가 있으면 예외가 발생합니다. – Placido

+0

예외를 유발하고 실제로 작동하는지 확인하십시오. – hakre

답변

1

검색어에 문제가 발생했습니다. execute()이 오류를 일으키기 때문에 t/c 블록에서 작동하지 않으므로 commit() 호출 전에 예외가 발생합니다. 그리고 t/c 블록 이후에 그것을 움직일 때 작동하는 유일한 이유는 그 시점에서 절차 적 단계이기 때문입니다. 오류 로그를 테일 링 해보십시오.

+0

초기 할당 후에'var_dump ($ stmt);'를 할 수 있습니까? 여러 쿼리 문은 지저분 해, 제대로 작동하는지 궁금합니다. –

+0

한 번에 하나의 쿼리를 수행하려고 시도했지만 작동합니다. 그리고이 경우 쿼리에 오류가 있으면 예외가 발생합니다. 예를 들어 INSERT 쿼리 만 남겨두고 PK 필드에 대한 중복 항목을 만들려고하면 다음 예외가 발생합니다. 'SQLSTATE [23000] : 무결성 제약 조건 위반 : 1062 키'reference '에 대한 중복 항목'5th ' 파일 - C : \ ... \ classes \ NestedSet.php line - 187' – Placido

+0

개별 명세서로 사용했을 때 동일한 거래 내에서 모두 가지고 있었습니까? –

관련 문제