27

PDOStatement用来查询数据库。每当我得到一个返回的行时,我希望它被提取到一个数组中,以$row[0]作为键,并将行中的后续元素作为值。

当然,我可以编写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) {
        // the simplest case for 2 columns, 
        // should add more to handle more columns
        $result[$row[0]][]=$row[1];
    }
    
    return $result;   
}

但我正在寻找一种现有的方法;有没有这样的方法已经存在?

为什么重新打开这个问题。

这里要问的显然是 PDO::FETCH_GROUP|PDO::FETCH_ASSOC 的组合。PDO::FETCH_KEY_PAIR 仅适用于 2 列结果。但是这里的示例是一个 2 列结果,仅用于简化问题中的代码,而不适用于所有情况。

4

5 回答 5

36

归功于 devdRew。在这里检查另一个问题

显然,您可以如答案中所述。我也检查过,效果很好。

$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_UNIQUE);
于 2012-08-19T13:44:23.293 回答
15
$stmt->fetchAll(PDO::FETCH_UNIQUE); 

虽然有点 hack 但实际上是唯一的方法,因为有人决定FETCH_KEY_PAIR 应该只需要 2 列结果集。

注意:第一列作为键使用,不会以任何其他形式在结果集中返回。

于 2013-06-24T04:49:10.440 回答
3

Afaik,在 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());

希望能帮助到你。

于 2012-08-24T15:22:50.893 回答
2

一些提示,您需要将正确的 fetch 样式传递给PDOStatement->fetch()方法,这样您就不会得到双重数据(数字和文本列名)。就像 $row[0] 和 $row['id'] 当你使用 PDO::FETCH_BOTH 时它们都包含相同的值。

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

至于您的问题,您必须获取所有结果,然后创建一个数组,其中 $row['id'] 作为键,结果行作为值 - 就像您正在做的那样。我围绕 PDO 构建了一个完整的 ORM 库,但我永远找不到任何东西可以自动执行此操作。

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

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

return $results;
于 2009-09-08T16:41:44.507 回答
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;
}
于 2012-08-23T14:08:40.980 回答