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?

¿Fue útil?

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 fetchAll . Ambas soluciones tienen implicaciones para el rendimiento de sus aplicaciones, así que piénselo dos veces si los conjuntos de resultados son grandes.

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.

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top