私はPDOで非常に奇妙な振る舞いをしています。時間がかかりすぎるため、詳細については説明しませんが、基本的に、単純なINSERTを実行する\ PDOStatementを再利用すると、PDO :: lastInsertId( )。
ステートメントを初めて実行すると、正常に機能し、正しいIDが返されます。後続の実行では、代わりに常に「0」が返されます。これはテスト間(PHPUnitのもの)でのみ発生するため、さらに奇妙です。つまり、test1(動作中)でpreparedステートメントを使用して挿入を実行すると、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;
}
}
何か案が?
乾杯