Domanda

Sto cercando di scrivere un iteratore per i risultati di un'istruzione PDO ma non riesco a trovare alcun modo per riavvolgere la prima riga. Vorrei evitare il sovraccarico di chiamare fetchAll e archiviare tutti i dati dei risultati.

// first loop works fine
foreach($statement as $result) {
    // do something with result
}

// but subsequent loops don't
foreach($statement as $result) {
    // never called 
}

Esiste un modo per ripristinare la dichiarazione o cercare la prima riga?

È stato utile?

Soluzione

Sono abbastanza sicuro che questo dipende dal database. Per questo motivo, è qualcosa che dovresti cercare di evitare. Tuttavia, penso che puoi ottenere ciò che desideri abilitando query bufferizzate . Se ciò non funziona, puoi sempre inserire il risultato in un array con fetchAll . Entrambe le soluzioni hanno implicazioni per le prestazioni delle applicazioni, quindi pensaci due volte, se i set di risultati sono grandi.

Altri suggerimenti

Questa piccola classe che ho scritto avvolge un PDOStatement. Memorizza solo i dati recuperati. Se non funziona, puoi spostare la cache per leggere e scrivere in un file.

// 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);
        }
    }
}

vedi slide 31 di questa presentazione , puoi fare una < code> $ statement- > rewind () se si applica a una query con buffer. Se si utilizza mysql, è possibile emulare query con buffer utilizzando PDO_MYSQL_ATTR_USE_BUFFERED_QUERY :

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

@NoahGoodrich ti ha indicato di dividere. Ecco un esempio che funziona sempre:

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

Probabilmente vorrai dare un'occhiata ad alcune delle classi PHP SPL che possono essere estese per fornire un accesso simile agli array agli oggetti.

Chiesto molto tempo fa ma al momento esiste un'altra soluzione.

Il metodo PDOStatement :: fetch () può ricevere un secondo parametro, l'orientamento del cursore, con una delle costanti PDO :: FETCH_ORI_ * . Questi parametri sono validi solo se PDOStatement vengono creati con l'attributo PDO :: ATTR_CURSOR come PDO :: CURSOR_SCROLL .

In questo modo puoi navigare come segue.

$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

Ulteriori informazioni in docs e < a href = "http://php.net/manual/en/pdo.constants.php" rel = "nofollow"> costanti predefinite DOP .

Nota: usato PDO :: FETCH_BOTH perché è l'impostazione predefinita, basta personalizzarlo per il proprio progetto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top