0
我有一個非常怪異的PDO行爲。我不會詳細討論太多的時間,但基本上我觀察到的是,當我重新使用執行簡單INSERT的\ PDOStatement時,在調用PDO :: lastInsertId時,我會得到一個錯誤的值)。準備好的語句和錯誤lastInsertId
我第一次執行該聲明,它工作正常,我找回正確的ID。後續執行將始終返回「0」。這更奇怪,因爲它只發生在測試(PHPUnit)之間。所以說我在test1(working)中使用準備好的語句執行插入,在test2中它會失敗。
當執行多次在非單元測試環境準備的語句(以一個簡單的PHP文件來回實例)這一切工作正常,最後插入的ID始終準確。確實很奇怪。
這裏的測試(注意PersistencyManagerInstance是PersistencyManager的只是一個普通的intsance):
<?php
class PersistencyManagerTest extends PHPUnit_Framework_TestCase {
const DELETE_ALL = "TRUNCATE user";
const ADD_USER = "INSERT INTO user values(null, :username, :password)";
const CHECK_USER_EXISTENCE = "SELECT * FROM user WHERE username = :username AND password = :password";
const DELETE_USER_BY_ID = "DELETE FROM user WHERE id = ?";
protected $manager = null;
public function __construct() {
$this->manager = new PersistencyManagerInstance(PDOFactory::build());
}
public function setUp() {
$this->manager->exec(self::DELETE_ALL);
}
public function tearDown() {
$this->manager->exec(self::DELETE_ALL);
}
public function testInsert() {
$user = new User("laurent", "password");
$id = $this->manager->insert(self::ADD_USER, $user->export());
$this->assertEquals("1", $id);
}
public function testInsertAgain() {
$user1 = new User("laurent1", "password1");
$id = $this->manager->insert(self::ADD_USER, $user1->export());
$this->assertEquals("1", $id);
}
public function testQuery() {
$user = new User("laurent", "password");
$this->manager->insert(self::ADD_USER, $user->export());
$results = $this->manager->query(self::CHECK_USER_EXISTENCE, $user->export());
$this->assertEquals(1, count($results));
}
public function testExec() {
$user = new User("laurent", "password---");
$id = $this->manager->insert(self::ADD_USER, $user->export());
$affected = $this->manager->exec(self::DELETE_USER_BY_ID, array($id));
$this->assertEquals(1, $affected);
}
}
而testInsertAgain不testInsert工作。
和這裏的類:
<?php
namespace memory\manager;
use \PDO;
abstract class PersistencyManager {
/**
* @var array An array of \PDOStatement objects
*/
protected static $ps = array();
/**
* @var \PDO
*/
protected $connection = null;
protected function prepareStmt($sql) {
// return $this->connection->prepare($sql);
$key = md5($sql);
if (!isset(self::$ps[$key])) {
self::$ps[$key] = $this->connection->prepare($sql);
}
return self::$ps[$key];
}
public function __construct(PDO $connection) {
$this->connection = $connection;
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function __destruct() {
$this->connection = null;
}
/**
* Good for SELECT operations. By default it fetches using arrays.
* @param string $sql
* @param array $values
* @param integer $fetchStyle
* @return array A list of matching elements (The elements' type depends on $fetchStyle)
*/
public function query($sql, array $values = array(), $fetchStyle = PDO::FETCH_ASSOC) {
$prepared = $this->prepareStmt($sql);
$prepared->execute($values);
$prepared->setFetchMode($fetchStyle);
$all = $prepared->fetchAll();
$prepared->closeCursor();
return $all;
}
/**
* Good for INSERT operations.
* @param string $sql
* @param array $values
* @return string Last inserted element's id in string format
*/
public function insert($sql, array $values = array()) {
$prepared = $this->prepareStmt($sql);
$prepared->execute($values);
$prepared->closeCursor();
return $this->connection->lastInsertId();
}
/**
* Good for all the remaining routines.
* @param string $sql
* @param array $values
* @return integer The number of effected rows
*/
public function exec($sql, array $values = array()) {
$prepared = $this->prepareStmt($sql);
$prepared->execute($values);
$count = $prepared->rowCount();
$prepared->closeCursor();
return $count;
}
}
任何想法?
乾杯
我想,如果你把下面的問題的代碼,使用戶不必從堆棧溢出導航離開來查看你的代碼,這將是最好的。只是一個建議:) –
做;)這樣好? – nourdine