Ich habe eine PDO-Transaktion, die ich versuche zu starten, die erste Abfrage erstellt einen Schalter und der zweite fügt Informationen darüber zu einer anderen Tabelle. Mein Problem ist, dass aus irgendeinem Grund die erste Abfrage nicht korrekt ausgeführt wird, aber die Transaktion festgeschrieben ist. (Im den folgenden PDO Klasse http://culttt.com/2012/10/01/roll-your-own-pdo-php-class/ mit)PDO Transaction funktioniert nicht
try{
//Insert into required tables
$db->beginTransaction();
$db->Query("INSERT INTO firewall (Name)VALUES(:Name)");
$db->bind(':Name',$Name);
$db->execute();
$db->Query("INSERT INTO firewall_switch (Switch_ID, firewall_id,customer_ID)VALUES(:Switch,LAST_INSERT_ID(),:Customer)");
$db->bind(':Switch',$switch);
$db->bind(':Customer',$customer);
$db->execute();
$db->endTransaction();
}catch(PDOException $e){
$db->cancelTransaction();
}
Hier finden Sie, was in SQL aus den Protokollen ausgeführt wird:
6 Query START TRANSACTION
6 Prepare [6] INSERT INTO firewall (Name)VALUES(?)
6 Prepare [7] INSERT INTO firewall_switch (Switch_ID, firewall_id,customer_ID)VALUES(?,LAST_INSERT_ID(),?)
6 Execute [7] INSERT INTO firewall_switch (Switch_ID, firewall_id,customer_ID)VALUES('2',LAST_INSERT_ID(),'164')
6 Query COMMIT
, wie Sie die erste Abfrage ausgeführt wird nie sehen können, aber der zweite Fall ist. Diese bestimmte Transaktion sollte zurückgesetzt werden, da eine doppelte ID nicht zulässig ist.
Wenn es keine Duplikate sind dann scheint die Transaktion wie erwartet vollständig, aber ich bin nicht sicher, warum Rollback funktioniert nicht ...
EDIT:
DB Klasse: Klasse Db {
private static $Connection = array();
public $connection;
private $dbh;
private $error;
private $stmt;
public static function GetConnection($connection)
{
if(!array_key_exists($connection,self::$Connection))
{
$className = __CLASS__;
self::$Connection[$connection] = new $className($connection);
}
return self::$Connection[$connection];
}
public function __construct($connection){
global $config;
//Load Settings
$this->id = uniqid();
$this->connection = $connection;
if(array_key_exists($connection,$config['connections']['database'])){
$dbConfig = $config['connections']['database'][$connection];
// Set DSN
$dsn = 'mysql:host=' . $dbConfig['host'] . ';port='.$dbConfig['port'].';dbname=' . $dbConfig['database'];
}
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instantiate
try{
$this->dbh = new PDO($dsn, $dbConfig['user'], $dbConfig['password'], $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
error_log($e->getMessage());
}
}
//Create the SQL Query
public function query($query){
$this->stmt = $this->dbh->prepare($query);
}
//Bind SQL Params
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
//Execute the SQL
public function execute($array = NULL){
if($array == NULL){
return $this->stmt->execute();
}else{
return $this->stmt->execute($array);
}
}
public function resultset(){
$this->execute();
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
//Return Single Record
public function single(){
$this->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
//Count rows in table
public function rowCount(){
return $this->stmt->rowCount();
}
//Show last ID Inserted into table
public function lastInsertId(){
return $this->dbh->lastInsertId();
}
//Transactions allows the tracking of multiple record inserts, should one fail all will rollback
public function beginTransaction(){
return $this->dbh->beginTransaction();
}
public function endTransaction(){
return $this->dbh->commit();
}
public function cancelTransaction(){
return $this->dbh->rollBack();
}
//Debug dumps the info that was contained in a perpared statement
public function debugDumpParams(){
return $this->stmt->debugDumpParams();
}
}
?>
DB-Struktur:
CREATE TABLE `firewall` (
`id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `Name_UNIQUE` (`Name`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=latin1
CREATE TABLE `firewall_switch` (
`id` int(11) NOT NULL auto_increment,
`Switch_ID` int(10) unsigned NOT NULL,
`firewall_id` int(10) unsigned NOT NULL,
`Customer_ID` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `fk_firewall_switch_Switch1_idx` (`Switch_ID`),
KEY `fk_firewall_switch_firewall1_idx` (`firewall_id`),
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1
Können Sie Ihren '$ db' Klassencode schreiben und wo Sie es auch konstruieren. Der Link zeigt nur, wie man einen schreibt, es gibt keine vollständige Klasse. Was ist die Art der Dublettenprüfung? Können Sie auch die Ergebnisse von SHOW CREATE TABLE auf jeder der beiden referenzierten Tabellen anzeigen? – Arth
Haben Sie PDO so eingestellt, dass Ausnahmen ausgelöst werden? Standardmäßig wird der stille Fehlermodus verwendet, bei dem Sie nach jeder Aktion explizit nach Fehlern suchen müssen. Siehe [Fehler und Fehlerbehandlung] (https://secure.php.net/manual/en/pdo.error-handling.php) für weitere Informationen. – eggyal
@Art Meine DB-Klasse sowie die DB-Struktur anhängen –