PHP PDOStatement: Fetch A Row, as the First Column as the Key of an Array

眉间皱痕 提交于 2019-12-18 11:45:23

问题


I am using PDOStatement to query the database. Whenever I get a returned row, I want it to be fetched into an array, with the $row[0] as the key, and the subsequent elements in the row as the values.

I can, of course, write a combination of foreach loops and if conditionals to do the job, such as the below:

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;

}

but I am looking for an existing method; is there such a method already exist?


回答1:


Credits go to devdRew. Check the other question here.

Apparently, you can as stated in the answer. I checked as well and it works great.

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

EDIT

This answer requires that you specify maximum 2 columns: 1 key and 1 value. If you need to retrieve more keys from the database, check the answer below and read @nullabilty's comment. For those who are lazy, here is his method:

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



回答2:


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

albeit a bit of a hack but really the only way to do this since someone decided FETCH_KEY_PAIR should require 2 column result set's only.

Note: first column is used a key and is not returned in the result set in any other form.




回答3:


Afaik, there are no existing method that would do that in PHP but there are a couple of ways you could achieve what you want.

One of the first being what Xeoncross said but a bit modified :

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

$res = array();

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

Otherwise, you can create a class with a __set() method to catch variable assignment:

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

Hope it helps.




回答4:


Some tips, you need to pass the right fetch style to the PDOStatement->fetch() method so that you don't end up with double data (numeric and textual column names). Like $row[0] and $row['id'] which both contain the same value when you use PDO::FETCH_BOTH.

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

As for your question, you will have to fetch all the results and then create an array with the $row['id'] as the key and the result row as the value - just like you are doing. I built an entire ORM library around PDO and I could never find anything to do this automatically.

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

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

return $results;



回答5:


Besides the two column table scenario, there's nothing at the PDO level to handle this, but you could write a reusable iterator for it, like this:

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

The constructor takes a PDOStatement and an optional fetch mode (numeric columns by default, but can be changed to PDO::FETCH_ASSOC for an associative array) and lets you iterate over the query results using a typical foreach.

Usage example:

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


来源:https://stackoverflow.com/questions/1387563/php-pdostatement-fetch-a-row-as-the-first-column-as-the-key-of-an-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!