¿Es posible rebobinar un resultado PDO?
Pregunta
Estoy tratando de escribir un iterador para resultados de una declaración PDO pero no puedo encontrar ninguna forma de rebobinar a la primera fila. Me gustaría evitar la sobrecarga de llamar a fetchAll y almacenar todos los datos de resultados.
// first loop works fine
foreach($statement as $result) {
// do something with result
}
// but subsequent loops don't
foreach($statement as $result) {
// never called
}
¿Hay alguna forma de restablecer la declaración o buscar la primera fila?
Solución
Estoy bastante seguro de que esto depende de la base de datos. Por eso, es algo que debes tratar de evitar. Sin embargo, creo que puede lograr lo que desea al habilitar consultas almacenadas . Si eso no funciona, siempre puede extraer el resultado en una matriz con
Otros consejos
Esta pequeña clase que escribí envuelve una declaración PDOS. Solo almacena los datos que se obtienen. Si esto no funciona, puede mover el caché para leer y escribir en un archivo.
// 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);
}
}
}
vea diapositiva 31 de esta presentación , puede hacer una < code> $ instrucción- > rewind () si se aplica a una consulta almacenada en búfer. Si usa mysql, puede emular consultas almacenadas utilizando PDO_MYSQL_ATTR_USE_BUFFERED_QUERY
:
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
@NoahGoodrich te señaló spl. Aquí hay un ejemplo que siempre funciona:
$it = new ArrayIterator($stmt->fetchAll());
Probablemente quiera echar un vistazo a algunas de las clases PHP SPL que se pueden extender para proporcionar acceso tipo matriz a los objetos.
- Biblioteca PHP estándar (SPL) lo haría específicamente te recomiendo que mires el ArrayIterator, ArrayObject y quizás la interfaz Iterator.
- Simple Tutorial
- Otro Tutorial rápido
Preguntado hace mucho tiempo, pero actualmente hay otra solución.
El método PDOStatement :: fetch ()
puede recibir un segundo parámetro, la orientación del cursor, con una de las constantes PDO :: FETCH_ORI_ *
. Estos parámetros solo son válidos si PDOStatement
se crean con el atributo PDO :: ATTR_CURSOR
como PDO :: CURSOR_SCROLL
.
De esta manera puede navegar de la siguiente manera.
$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
Más información en docs y < a href = "http://php.net/manual/en/pdo.constants.php" rel = "nofollow"> constantes predefinidas PDO .
Nota: usó PDO :: FETCH_BOTH
porque es el valor predeterminado, solo personalícelo para su proyecto.