2009-09-07 48 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

你的代碼實際上是將行分配在非唯一鍵上,這也是可能的答案的要求嗎? – 2012-08-25 13:08:42

回答

2

一些提示,您需要將正確的獲取樣式傳遞給PDOStatement->fetch()方法,以便最終不會產生雙重數據(數字和文本列名)。像使用PDO :: FETCH_BOTH時,它們包含相同的值的$ row [0]和$ row ['id']一樣。

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

至於你的問題,你必須獲取所有結果,然後創建一個$行[「身份證」]作爲重點和結果行作爲值數組 - 就像你正在做的。我在PDO周圍建立了一個完整的ORM庫,我永遠無法找到任何可以自動完成的任務。

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

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

return $results; 
+0

這與使用foreach循環有何不同,這正是我們試圖避免的情況? – 2012-08-24 04:25:57

22

Credits轉到devdRew。 Check the other question here

顯然,你可以如答案中所述。我也檢查,它很好。

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

編輯

這個答案需要您指定最多2列:1個鍵和1倍的值。如果您需要從數據庫中檢索更多密鑰,請查看下面的答案並閱讀@nullabilty的評論。對於那些誰是懶惰的,這裏是他的方法:

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

這是唯一一種將第一列作爲關鍵字的方法,如果您需要附加列,CONCAT或類似附加字段作爲第二列值的分隔字符串,並在使用該值之前使用'explode'有一個數組。 – 2012-08-24 04:19:54

+0

@ nickl-爲此使用'CONCAT'是一個可怕的想法;這個答案應該專門用於鍵值對,這是它設計要做的事情。 – 2012-08-27 01:56:25

+0

你讓賞金過期了嗎? – 2012-08-27 14:23:23

1

除了兩列的表的情況下,沒有什麼在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'來改善它,並且如果你能夠幫助它,總是避免'作爲$ key =>#value'。只要計數也被引用,你會發現在引用'array_keys'上的for循環會產生更好的結果。 'for($ i = 0; $ i 2012-08-24 04:36:58

+0

@nickl迭代器總是比「普通」數組更昂貴,因爲額外的代碼會在每個循環中執行,而這些循環不會通過引用實例而消失;刪除'key =>值'也不是一個選項,因爲沒有辦法獲得密鑰,否則:) – 2012-08-24 04:46:36

+0

使用迭代器並仍然獲得密鑰的替代方法可能與do..while或while在這個問題上以及我可以考慮幾個循環即。 ($ it = new ArrayIterator($ data); $ it-> valid(); $ it-> next())echo $ it-> key()。' =>'。 $ it-> current();'但我相信你也考慮過這些。=) – 2012-08-31 22:11:40

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 2013-11-19 21:39:14

+0

不錯的加法那裏thx – Louis 2013-11-19 23:14:37

+0

注意:第一列使用一個鍵,並不會以任何其他形式返回結果集。 如果您想獲得列是結果,您仍然可以使用「SELECT firstcolumn AS id,firstcolumn,secondcolumn ...」複製第一列 – 2015-11-18 15:08:13

相關問題