我对PDO有一种非常奇怪的行为。我不会详细介绍,因为它会花费太多时间,但基本上我观察到的是,当我重新使用一个执行简单INSERT的\ PDOStatement时,我在调用PDO :: lastInsertId时错误地获取了一个错误的值( )。
我第一次执行该语句时工作正常,我找回了正确的ID。相反,后续执行将始终返回“0”。这更奇怪,因为它只发生在测试之间(PHPUnit)。所以说我在test1(工作)中使用预处理语句执行插入,在test2中它将失败。
当在非单元测试环境中执行多次预处理语句时(在实例中的简单php文件中),它一切正常,最后插入的id总是准确的。确实非常奇怪。
这是测试(请注意,PersistencyManagerInstance只是PersistencyManager的简单内容):
<?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);
}
}
testInsert在testInsertAgain没有的情况下有效。
这是班级:
<?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;
}
}
有什么想法吗?
干杯
答案 0 :(得分:0)