PHP PDOStatement: извлекать строку как первый столбец как ключ массива
Я использую 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)
{
$result[$row[0]][]=$row[1]; // the simplest case for 2 columns, should add more to handle more columns
}
return $result;
}
но я ищу существующий метод; такой метод уже существует?
5 ответов
Кредиты идут на 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_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC);
$stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE);
хоть и немного хакерский, но на самом деле единственный способ сделать это, так как кто-то решил, что FETCH_KEY_PAIR должен требовать только 2 набора результатов столбца.
Примечание: в первом столбце используется ключ, и он не возвращается в наборе результатов в любой другой форме.
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());
Надеюсь, поможет.
Некоторые советы: вам нужно передать правильный стиль выборки методу PDOStatement->fetch(), чтобы вы не получили двойные данные (числовые и текстовые имена столбцов). Например, $row[0] и $row['id'], которые содержат одинаковое значение при использовании PDO::FETCH_BOTH.
$result = $dbh->query($sqlString);
while ($row = $result->fetch(PDO::FETCH_NUM)) {
...
Что касается вашего вопроса, вам придется извлечь все результаты, а затем создать массив с $row['id'] в качестве ключа и строкой результатов в качестве значения - как вы делаете. Я построил целую библиотеку ORM вокруг PDO, и я никогда не мог найти ничего, чтобы сделать это автоматически.
$result = $dbh->query($sqlString);
$results = array();
while ($row = $result->fetch(PDO::FETCH_NUM)) {
$results[$row[0]] = $row;
}
return $results;
Помимо сценария с двумя столбцами, на уровне 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;
}