2008-11-10 12 views
14

Estoy tratando de escribir un iterador para los 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.¿Es posible rebobinar un resultado de PDO?

// 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 manera de restablecer la declaración o buscar la primera fila?

Respuesta

10

estoy bastante seguro de que esta es la base de datos dependiente. Por eso, es algo que debes tratar de evitar. Sin embargo, creo que puede lograr lo que quiere al habilitar buffered queries. Si eso no funciona, siempre puede extraer el resultado en una matriz con fetchAll. Ambas soluciones tienen implicaciones para el rendimiento de sus aplicaciones, así que piénselo dos veces, si los resultados son grandes.

1

Probablemente quiera echar un vistazo a algunas de las clases SPL de PHP que se pueden ampliar para proporcionar acceso tipo matriz a los objetos.

+2

PdoStatement ya implementa Traverseable – troelskn

8

ver slide 31 from this presentation, puede hacer un $statement->rewind() si se aplica a una consulta en búfer. Si utiliza MySQL, puede emular consultas buffer mediante el uso de PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:

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

@NoahGoodrich que apuntó a SPL. Aquí hay un ejemplo que siempre funciona:

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

Esta pequeña clase que escribí envuelve un PDOStatement. Solo almacena los datos que se obtienen. Si esto no funciona, podría mover la memoria 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); 
     } 
    } 
} 
0

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 el PDOStatement se crea 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 PDO predefined constants.

Nota: utilizado PDO::FETCH_BOTH porque es el predeterminado, simplemente personalícelo para su proyecto.

Cuestiones relacionadas