Переопределение fetch () для PDO при извлечении с использованием foreach - PullRequest
3 голосов
/ 26 июля 2010

Я расширил PDOStatement и изменил метод fetch(), чтобы привести значения типов типов timestamp и массивов в PostgreSQL к DateTime и собственному массиву.Это работает как задумано, но я не могу переопределить поведение при использовании оператора в 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)
}

Ответы [ 2 ]

3 голосов
/ 26 июля 2010

Класс PDOStatement реализует встроенный только для внутреннего использования интерфейс Traversable.Реализуемый итератор обходит открытый метод PDOStatement::fetch().

0 голосов
/ 26 июля 2010

Я использую что-то вроде этого:

$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$sql = 'select * from table';
$stmt = $db->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT))
{
    // do stuff
}

Так что единственное, что вам нужно сделать, это установить некоторые параметры:)

...