2009-09-07 20 views
19

私はPDOStatementを使用してデータベースにクエリしています。返された行を取得するたびに、$row[0]をキーとして配列内にフェッチし、その行の次の要素を値として取得します。PHP PDOStatement:配列のキーとして最初の列として行を取得

私は、もちろん、例えば、以下のような仕事をするためにforeachループとif条件文の組み合わせを記述することができます。

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; 

} 

が、私は、既存の方法を探しています。そのような方法はありますかすでにが存在しますか?

+0

コードでは、一意でないキーの行が実際にグループ化されますが、それは可能な回答の要件ですか? –

答えて

2

ヒントいくつかのヒントでは、ダブルデータ(数値とテキストの列名)にならないように、正しいフェッチスタイルをPDOStatement->fetch()メソッドに渡す必要があります。 $ row [0]や$ row ['id']のように、PDO :: FETCH_BOTHを使うときには同じ値を含みます。

あなたの質問については
$result = $dbh->query($sqlString); 
while ($row = $result->fetch(PDO::FETCH_NUM)) { 
... 

、あなたはすべての結果をフェッチし、キーと値として結果の行として$行[「ID」]の配列を作成する必要があります - あなたがやっているだけのよう。私はPDOの周りにORMライブラリ全体を構築しました。私はこれを自動的に行うことができませんでした。

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

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

return $results; 
+0

これはforeachループを使用する方法とどのように違うのですか?これは回避しようとしているものですか? –

22

クレジットはdevdRewに行きます。 Check the other question here

明らかに、回答に記載されているとおりです。私も同様にチェックし、それは素晴らしい作品です。 1つのキーと1つの値:

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

EDIT

この答えは、最大2列を指定する必要があります。データベースからさらに鍵を取得する必要がある場合は、以下の答えを確認して@nullabiltyのコメントを読んでください。怠惰ある人のために、ここでの彼の方法は次のとおりです。

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

これは、最初の列をキーとして使用する唯一の方法です。追加の列、CONCATなどの追加フィールドを2列目の値の区切り文字列として使用し、値を使用する前に配列を持つために 'explode'を使用する必要があります。 –

+0

@ nickl-この目的のために 'CONCAT'を使うのは恐ろしい考えです。この回答は、キーと値のペアにのみ使用する必要があります。 –

+0

賞金の有効期限は切れますか? –

1

2列の表のシナリオに加えて、これを処理するPDOレベルでは何もありませんが、あなたはこのように、それのための再利用可能なイテレータを書くことができます:

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

コンストラクタはPDOStatementを取り、オプションは、(デフォルトでは数値列が、連想配列のためPDO::FETCH_ASSOCに変更することができます)モードを取得し、あなたは典型的なforeachを使用してクエリ結果を反復することができます。

使用例:

$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点=)しかし、あなたはこの方法より高価見つける元のシナリオ。最初に 'new Iterator'を参照することでこれを改善し、助けることができるなら常に' as $ key =>#value'を避けてください。参照される 'array_keys'のforループは、カウントも参照される限り、より良い結果をもたらすことがわかります。 'for($ i = 0; $ i

+0

@nicklイテレータは、 "プレーン"配列よりも常に高価です。なぜなら、余分なコードは、インスタンスを参照することによって遠ざかることのないすべてのループで実行されるからです。それ以外の場合はキーを取得する方法がないので、 'key => value'を削除することもオプションではありません:) –

+0

イテレータを使用してキーを取得する別の方法は、do..whileまたはwhileのことです。私はいくつかのループ、すなわち考えることができます。 $ it-> key()。 '); $ this-> key()。'のようになります。 => '。 $ it-> current(); 'しかし、私はあなたもこれらについて考えていると確信しています。=) –

3

私の知る限り、PHPではなく、いくつかの方法があり、あなたが望むものを達成できることを行うだろう既存の方法はありません。

最初の一つはXeoncrossが言っているが、少しは修正:

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

$res = array(); 

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

そうでない場合、あなたは変数の代入をキャッチするために__set()メソッドを持つクラスを作成することができます。

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()); 

はそれが役に立てば幸い。ハックのビットはいえ

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

が、本当に誰かdecided FETCH_KEY_PAIRので、これを行うための唯一の方法は、2列の結果セットの唯一のを要求すべきです。

注:最初の列はキーとして使用され、他の形式の結果セットには戻されません。

+13

ありがとう、私は 'PDO :: FETCH_GROUP | PDO :: FETCH_UNIQUE | PDO :: FETCH_ASSOC'を実行して、必要なものを正確に取得します。 – nullability

+0

nice add thx – Louis

+0

注:最初の列はキーとして使用され、他の形式の結果セットには戻されません。 カラムを取得する場合は、 "SELECT firstcolumn AS id、firstcolumn、secondcolumn ..."を使用して最初のカラムを複製することもできます –

関連する問題