Возможно ли перемотать результат PDO?

Я пытаюсь написать итератор для результатов из инструкции PDO, но я не могу найти способ перемотки в первую строку. Я хотел бы избежать накладных расходов на вызов fetchAll и сохранение всех данных результата.

// first loop works fine foreach($statement as $result) { // do something with result } // but subsequent loops don't foreach($statement as $result) { // never called } 

Есть ли способ переустановки заявления или поиска первой строки?

Related of "Возможно ли перемотать результат PDO?"

Я уверен, что это зависит от базы данных. Из-за этого вы должны избегать этого. Однако, я думаю, вы можете достичь того, чего хотите, включив буферизованные запросы . Если это не сработает, вы всегда можете вывести результат в массив с помощью fetchAll . Оба решения влияют на производительность ваших приложений, поэтому дважды подумайте об этом, если набор результатов большой.

Этот маленький класс, который я написал, обертывает PDOStatement. Он хранит только данные, которые извлекаются. Если это не сработает, вы можете переместить кеш для чтения и записи в файл.

 // Wrap a PDOStatement to iterate through all result rows. Uses a // local cache to allow rewinding. class PDOStatementIterator implements Iterator { public $stmt, $cache, $next; public function __construct($stmt) { $this->cache = array(); $this->stmt = $stmt; } public function rewind() { reset($this->cache); $this->next(); } public function valid() { return (FALSE !== $this->next); } public function current() { return $this->next[1]; } public function key() { return $this->next[0]; } public function next() { // Try to get the next element in our data cache. $this->next = each($this->cache); // Past the end of the data cache if (FALSE === $this->next) { // Fetch the next row of data $row = $this->stmt->fetch(PDO::FETCH_ASSOC); // Fetch successful if ($row) { // Add row to data cache $this->cache[] = $row; } $this->next = each($this->cache); } } } 

см. слайд 31 из этой презентации , вы можете сделать $statement->rewind() если он применяется к буферизованному запросу. Если вы используете mysql, вы можете эмулировать буферизованные запросы с помощью PDO_MYSQL_ATTR_USE_BUFFERED_QUERY :

 $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); 

@NoahGoodrich указал вам на spl. Вот пример, который всегда работает:

 $it = new ArrayIterator($stmt->fetchAll()); 

Вероятно, вы захотите взглянуть на некоторые из классов PHP SPL, которые могут быть расширены для обеспечения доступа к объектам, подобным массиву.

  • Стандартная библиотека PHP (SPL) Я бы рекомендовал вам взглянуть на интерфейс ArrayIterator, ArrayObject и, возможно, на интерфейс Iterator.
  • Простой учебник
  • Другой быстрый учебник

Спрошено давно, но в настоящее время есть еще одно решение.

Метод PDOStatement::fetch() может принимать второй параметр, ориентацию курсора, с одной из констант PDO::FETCH_ORI_* . Этот параметр действителен только в том случае, если PDOStatement создается с атрибутом PDO::ATTR_CURSOR как PDO::CURSOR_SCROLL .

Таким образом вы можете перемещаться следующим образом.

 $sql = "Select * From Tabela"; $statement = $db->prepare($sql, array( PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, )); $statement->execute(); $statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT); // return next $statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_PRIOR); // return previous $statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST); // return first $statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_LAST); // return last $statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $n); // return to $n position $statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_REL, $n); // return to $n position relative to current 

Дополнительная информация в документах и предопределенных константах PDO .

Примечание: используемый PDO::FETCH_BOTH поскольку он по умолчанию, просто настройте его для своего проекта.