2009-09-07 7 views
19

Ich verwende PDOStatement, um die Datenbank abzufragen. Immer wenn ich eine zurückgegebene Zeile erhalte, möchte ich, dass sie in ein Array mit dem Schlüssel $row[0] und den nachfolgenden Elementen in der Zeile als Werte abgerufen wird.PHP PDOStatement: Eine Zeile als erste Spalte als Schlüssel eines Arrays abrufen

Ich kann natürlich eine Kombination aus foreach Schleifen schreiben und if conditionals den Job, wie die folgenden zu tun:

private static function GetMySQLResult($dbname, $sqlString) { 


     $dbh = self::ConstructPDOObject($dbname); 
     $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

     $result=array(); 
     foreach ($dbh->query($sqlString) as $row) 
     { 
      $result[$row[0]][]=$row[1]; // the simplest case for 2 columns, should add more to handle more columns 

     } 

     return $result; 

} 

aber ich für eine bestehende Methode suchen; Gibt es eine solche Methode bereits existieren?

+0

Ihr Code gruppiert tatsächlich Zeilen auf einem nicht eindeutigen Schlüssel, ist das auch eine Voraussetzung für eine mögliche Antwort? –

Antwort

2

Einige Tipps, Sie müssen den richtigen Abrufstil an die PDOStatement->fetch() Methode übergeben, so dass Sie nicht mit doppelten Daten (numerische und textuelle Spaltennamen) enden. Wie $ row [0] und $ row ['id'], die beide denselben Wert enthalten, wenn Sie PDO :: FETCH_BOTH verwenden.

$result = $dbh->query($sqlString); 
while ($row = $result->fetch(PDO::FETCH_NUM)) { 
... 

Was Ihre Frage, werden Sie alle Ergebnisse holen müssen und dann ein Array mit dem $ row [ ‚id‘] als Schlüssel und die Ergebniszeile als Wert schaffen - genau wie Sie tun, . Ich habe eine komplette ORM-Bibliothek um PDO herum gebaut und ich konnte nie automatisch etwas dafür finden.

$result = $dbh->query($sqlString); 

$results = array(); 
while ($row = $result->fetch(PDO::FETCH_NUM)) { 
    $results[$row[0]] = $row; 
} 

return $results; 
+0

Wie unterscheidet sich dies von der Verwendung einer foreach-Schleife, die wir zu vermeiden versuchen? –

22

Credits gehen zu devdRew. Check the other question here.

Offenbar können Sie wie in der Antwort angegeben. Ich habe auch überprüft und es funktioniert super.

$q = $db->query("SELECT `name` AS name, `value` AS value FROM `settings`;"); 
$r = $q->fetchAll(PDO::FETCH_KEY_PAIR); 

EDIT

Diese Antwort erfordert, dass Sie maximal 2 Spalten festlegen: Taste 1 und 1 Wert. Wenn Sie mehr Schlüssel aus der Datenbank abrufen müssen, überprüfen Sie die Antwort unten und lesen Sie den Kommentar @nullabilty. Für diejenigen, die faul sind, hier ist seine Methode:

$q->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC); 
+0

Dies ist die einzige Methode, die die erste Spalte als Schlüssel verwendet, falls Sie zusätzliche Spalten benötigen, CONCAT o.ä. die zusätzlichen Felder als Zeichenfolge mit Trennzeichen für den zweiten Spaltenwert und "explode" verwenden, um ein Array zu verwenden. –

+0

@ nickl- mit 'CONCAT' zu diesem Zweck ist eine schreckliche Idee; Diese Antwort sollte ausschließlich für Schlüssel/Wert-Paare verwendet werden, für die sie entwickelt wurde. –

+0

Lassen Sie das Kopfgeld ablaufen? –

1

Neben der zweispaltige Tabelle Szenario gibt es nichts an der PDO Ebene zu handhaben, aber man konnte eine wiederverwendbare Iterator für sie, so schreiben:

class FirstColumnKeyIterator implements Iterator 
{ 
    private $stmt; 
    private $key; 
    private $data; 
    private $mode; 

    public function __construct(PDOStatement $stmt, $fetch_mode = PDO::FETCH_NUM) 
    { 
     $this->stmt = $stmt; 
     $this->mode = $fetch_mode; 
     $this->fetch(); 
    } 

    private function fetch() 
    { 
     if (false !== ($this->data = $this->stmt->fetch($this->mode))) { 
      $this->key = current(array_splice($this->data, 0, 1)); 
     } 
    } 

    public function rewind() 
    { 
     // nil operation 
    } 

    public function key() 
    { 
     return $this->key; 
    } 

    public function current() 
    { 
     return $this->data; 
    } 

    public function next() 
    { 
     $this->fetch(); 
    } 

    public function valid() 
    { 
     return false !== $this->data; 
    } 
} 

Der Konstruktor nimmt einen PDOStatement und einen optionalen Modus holen (numerische Spalten standardmäßig, kann aber auf PDO::FETCH_ASSOC für ein assoziatives Array geändert werden) und können Sie die Abfrageergebnisse mit Hilfe eines typischen foreach iterieren.

Anwendungsbeispiel:

$dbh = new PDO(/* etc */); 

$stmt = $dbh->query('SELECT * FROM accounts'); 
foreach (new FirstColumnKeyIterator($stmt, PDO::FETCH_ASSOC) as $key => $value) { 
     echo $key, ' = ', print_r($value, true), PHP_EOL; 
} 
+0

10 Punkte für Kreativität =) aber du wirst diesen Weg teurer finden als die ursprüngliches Szenario. Sie können dies verbessern, indem Sie zuerst auf den 'neuen Iterator' verweisen und immer' '$ key => # value' vermeiden, wenn Sie ihm helfen können. Sie werden feststellen, dass eine for-Schleife auf einem referenzierten 'array_keys' bessere Ergebnisse liefert, solange auf den Zählwert auch Bezug genommen wird. 'für ($ i = 0; $ i

+0

@nickl-Iteratoren sind immer teurer als ein "normales" Array, weil bei jeder Schleife zusätzlicher Code ausgeführt wird, der nicht durch Referenzieren der Instanz verschwindet; das Entfernen des 'key => value' ist auch keine Option, da es keine Möglichkeit gibt, den Schlüssel anderweitig zu erhalten :) –

+0

alternative Möglichkeiten, einen Iterator zu verwenden und trotzdem den Schlüssel zu erhalten, könnte mit do..while oder while for that und and sein Ich kann mir verschiedene for loops vorstellen, d. 'for ($ it = neuer ArrayIterator ($ data); $ it-> gültiger(); $ it-> next()) echo $ it-> key(). ' => '. $ it-> current(); 'aber ich bin mir sicher, dass du auch darüber nachgedacht hast.=) –

3

Afaik gibt es keine Methode, die das in PHP tun würde, aber es gibt ein paar Möglichkeiten, können Sie erreichen, was Sie wollen.

Einer der ersten ist, was Xeoncross sagte, aber ein wenig geändert:

$pdostmt = $pdo->query("SELECT ... FROM your_table"); 

$res = array(); 

foreach ($pdostmt->fetchAll(PDO::FETCH_ASSOC) as $row) 
{ 
    $res[array_shift($row)] = $row; 
} 

Andernfalls Sie eine Klasse mit einer __set() Methode erstellen können variable Zuordnung zu fangen:

class at_res 
{ 
    public $key; 
    public $values = array(); 
    protected $flag = true; 

    public function __set($var, $value) 
    { 
    if ($this->flag) 
    { 
     $this->key = $value; 
     $this->flag = false; 
    } 
    else 
    { 
     $this->values[$var] = $value; 
    } 
    } 

    public function extract() 
    { 
    return array($this->key => $this->values); 
    } 
} 


$pdo = new PDO(...); 

$pdostmt = $pdo->query("SELECT ... FROM your_table"); 

$res = $pdostmt->fetchObject('at_res'); 

var_dump($res->extract()); 

Hoffe, es hilft .

13
$stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE); 

wenn auch ein bisschen wie ein Hack, aber wirklich der einzige Weg, dies decided FETCH_KEY_PAIR da jemand tun sollte 2 Spalte Ergebnis-Set nur erfordern.

Hinweis: Die erste Spalte wird als Schlüssel verwendet und nicht in der Ergebnismenge in einer anderen Form zurückgegeben.

+13

Danke, habe ich meine auf 'PDO :: FETCH_GROUP | PDO :: FETCH_UNIQUE | erweitert PDO :: FETCH_ASSOC' um genau das zu bekommen was ich brauche. – nullability

+0

nice addition there thx – Louis

+0

Hinweis: erste Spalte verwendet einen Schlüssel und wird nicht in der Ergebnismenge in einer anderen Form zurückgegeben. Sie können immer noch Ihre erste Spalte mit "SELECT Firstcolumn AS ID, erste Spalte, zweite Spalte ..." duplizieren, wenn Sie die Spalte Ergebnisse erhalten möchten –

Verwandte Themen