2012-10-13 3 views
0

J'ai écrit une classe de base de données il y a quelque temps, je l'utilise pour la plupart des projets et récemment étendu la classe pour travailler avec des transactions.PHP mysql_query transactions pas reculer

La classe Transaction ci-dessous ne semble pas fonctionner correctement, le serveur est MySQL innoDB et j'ai vérifié que les transactions fonctionnent sur ma base de données (avec PHPMyAdmin). Donc c'est évidemment une erreur dans mon code ou mon malentendu.

<?php 

/** 
* Description of Database 
* 
* @author http://stackoverflow.com/users/820750/gerve 
*/ 
class Database { 

    private $connection; 

    public function __construct($dbServer, $dbName, $dbUser, $dbPassword) { 
     $this->connection = mysql_connect($dbServer, $dbUser, $dbPassword); 
     mysql_select_db($dbName, $this->connection); 
    } 

    public function query($query, $die = true) { 
     return new Query($query, $this->connection, $die); 
    } 

    public function escape($param) { 
     return mysql_real_escape_string($param, $this->connection); 
    } 

    public function transaction() { 
     return new Transaction($this->connection); 
    } 

} 

class Query { 

    private $query; 
    public $count; 
    public $countModified; 
    public $queryString; 


    public function __construct($query, $link_identifier, $die = true) { 
     if($die){ 
      $this->query = mysql_query($query, $link_identifier) or die(mysql_error()); 
     } 
     else{ 
      $this->query = mysql_query($query, $link_identifier); 
     } 

     $this->count = is_resource($this->query) ? mysql_num_rows($this->query) : 0; 
     $this->countModified = mysql_affected_rows($link_identifier); 

     $this->queryString = $query; 
    } 

    public function nextRow() { 
     return mysql_fetch_object($this->query); 
    } 

    public function allRows() { 
     $array = array(); 

     while($row = mysql_fetch_object($this->query)){ 
      $array[] = $row; 
     } 

     return $row; 
    } 

} 

class Transaction { 

    private $connection; 
    private $isAlive; 

    public function __construct($link_identifier) { 
     $this->connection = $link_identifier; 
     $this->query("BEGIN"); 
     $this->isAlive = true; 
    } 

    public function query($query) { 
     if($this->isAlive){ 
      $q = new Query($query, $this->connection, false); 
      if(mysql_error()){ 
       $this->rollBack(); 
       return false; 
      } 
      else{ 
       return $q; 
      } 
     } 
    } 

    public function rollBack() { 
     if($this->isAlive){ 
      $this->query("ROLLBACK"); 
      $this->isAlive = false; 
     } 
    } 

    public function commit() { 
     if($this->isAlive){ 
      $this->query("COMMIT"); 
      $this->isAlive = false; 
      return true; 
     } 
     else{ 
      return false; 
     } 
    } 

} 

?> 

EDIT - Exemple d'utilisation des classes

$DB = new Database(dbServer, dbName, dbUser, dbPassword); 
$transaction = $DB->transaction(); 

$transaction->query("INSERT INTO myTable `c1`, `c2` VALUES('1', '2')"); //Works 
$transaction->query("INSERT INTO jhsdjkag 5dafa 545"); //Fails 
$transaction->query("INSERT INTO myTable2 `c1`, `c2` VALUES('3', '4')"); //Works 

$transaction->commit(); 

Le code ci-dessus ne doit pas insérer des lignes dans la base de données, la deuxième requête a échoué ne devrait réussir.

Mon problème est qu'il ne se rétablit pas, toujours les lignes sont insérées indépendamment des requêtes défaillantes.

+0

Veuillez ne pas utiliser les fonctions 'mysql_ *' pour le nouveau code. Ils ne sont plus entretenus et la communauté a commencé le [processus de dépréciation] (http://goo.gl/KJveJ). Voir la [** boîte rouge **] (http://goo.gl/GPmFd)? Au lieu de cela, vous devriez en apprendre davantage sur les [instructions préparées] (http://goo.gl/vn8zQ) et utiliser soit [PDO] (http://php.net/pdo) ou [MySQLi] (http://php.net/ mysqli). Si vous ne pouvez pas décider, [cet article] (http://goo.gl/3gqF9) aidera à choisir. Si vous voulez apprendre, [voici un bon tutoriel sur les PDO] (http://goo.gl/vFWnC). – PeeHaa

+0

I.e. il suffit d'utiliser quelque chose qui supporte les transactions par défaut et qui est toujours une fonctionnalité supportée. – PeeHaa

+0

@PeeHaa: Merci, considérera PDO. Mais je voudrais toujours réparer celui-ci pour l'instant. – Drahcir

Répondre

0

je trouve qu'il ya eu une erreur dans le code, juste dans le __construct(). Il était assez simple, je viens de changer 1 ligne:

DE:

public function __construct($link_identifier) { 
    $this->connection = $link_identifier; 
    $this->query("BEGIN"); 
    $this->isAlive = true; 
} 

À:

public function __construct($link_identifier) { 
    $this->connection = $link_identifier; 
    $this->isAlive = true; 
    $this->query("BEGIN"); 
} 

-> isAlive était défini après la première requête "BEGIN" , ce qui signifie que BEGIN n'a jamais été envoyé.

0

essayez d'utiliser START TRANSACTION au lieu de BEGIN

par la façon dont START TRANSACTION vous permettra d'utiliser WITH CONSISTENT SNAPSHOT:

L'option WITH SNAPSHOT CONFORME démarre un consistent read pour les moteurs de stockage qui en sont capables. Ceci s'applique uniquement à InnoDB.

source: MySQL Documentation