Я продлил PDOStatement
и модифицировал метод fetch()
для получения значений типа timestamp и массивов типов в PostgreSQL до DateTime и собственного массива. Это работает по назначению, но я не могу переопределить поведение при использовании инструкции в foreach.Переопределение fetch() для PDO при извлечении с использованием foreach
Я решил это, возвращая строки в объект, реализующий ArrayAccess, IteratorAggregate и Countable. Однако я не удовлетворен этим решением и просто хочу вернуть чистый массив.
Пример:
class ExtendedStatement extends PDOStatement { protected function __construct() { $this->setFetchMode(PDO::FETCH_ASSOC); } public function fetch( $fetch_style = PDO::FETCH_ASSOC, $cursor_orientation = PDO::FETCH_ORI_NEXT, $cursor_offset = 0) { $r = parent::fetch($fetch_style, $cursor_orientation, $cursor_offset); if (is_array($r)) { $r["extradata"] = TRUE; } return $r; } } $db = new PDO("sqlite::memory:"); $db->setAttribute( PDO::ATTR_STATEMENT_CLASS, array("ExtendedStatement", array($db))); $db->exec("CREATE TABLE example(id INTEGER PRIMARY KEY, name VARCHAR)"); $db->exec("INSERT INTO example(name) VALUES('test')"); // This is what is does $s = $db->prepare("SELECT * FROM example"); $s->execute(); foreach ($s as $r) { var_dump($r); } $s->closeCursor(); // This is how I want it to be $s = $db->prepare("SELECT * FROM example"); $s->execute(); while ($r = $s->fetch()) { var_dump($r); } $s->closeCursor(); // This is how I want it to be $s = $db->prepare("SELECT * FROM example"); $s->execute(); var_dump($s->fetch()); $s->closeCursor();
Выход:
array(2) { ["id"]=> string(1) "1" ["name"]=> string(4) "test" } array(3) { ["id"]=> string(1) "1" ["name"]=> string(4) "test" ["extradata"]=> bool(true) } array(3) { ["id"]=> string(1) "1" ["name"]=> string(4) "test" ["extradata"]=> bool(true) }
Можете ли вы показать код, который делает работу, как и ожидалось, и не работает, как ожидается? Если вы переопределили 'fetch', он всегда должен работать« правильно ». – Charles
Обновлено с примером. – runfalk
Работает ли он нормально, когда вы заменяете foreach на 'while ($ r = $ s-> fetch()) {'? Кроме того, имейте в виду, что результат, возвращаемый вызовом 'parent :: fetch', может не быть массивом, он может быть нулевым. Вероятно, вы должны добавить проверку 'is_array' или что-то подобное. – Charles