Skip to content
Oleg Grigoriev edited this page Mar 27, 2016 · 16 revisions

Разбор результата

Итак, выполнять запрос мы научились, теперь займёмся разбором полученного результата.

Формат, в котором требуется представить результат, задаётся третьим аргументом метода query(). В примере формат el - одно значение.

$pattern = 'SELECT `email` FROM `users` WHERE `user_id`=?i';
$data = [$userId];
$email = $db->query($pattern, $data, 'el');

Если не указать третий аргумент (или указать NULL), query возвращает объект с интерфейсом go\DB\Result уже из которого можно получать результат. Методы данного объекта соответствуют одноимённый форматам из аргумента query. То есть следующие три варианта идентичны:

$email = $db->query($pattern, $data, 'el');
$email = $db->query($pattern, $data)->el();
$result = $db->query($pattern, $data);
$email = $result->el();

Дополнительные параметры формата

Имя формата может содержать дополнительные параметры. При использовании аргумента query(), они записываются через двоеточие после имени формата:

$result = $db->query($pattern, $data, 'assoc:num');

При использовании возвращаемого объекта, параметры передаются аргументом в метод разбора:

$result = $db->query($pattern, $data)->assoc('num');

Выборка (SELECT) нескольких строк (записей)

assoc, assoc:{$key}

В качестве результата в этих случаях возвращается массив, каждый элемент которого соответствует строке в выборке. В случае пустой выборки получается пустой массив.

Результат выборки представляется в виде массива ассоциативных массивов, что примерно соответствует перебору результата через while ($row = mysql_fetch_assoc($res)):

$users = $db->query('SELECT * FROM `users`')->assoc();
echo 'Selected '.count($users).' users';
foreach ($users as $user) {
    echo 'Params of another user:';
    var_dump($user);
}

То есть получается примерно следующее:

[
    0 => [
        'user_id' => 1,
        'name' => 'Vasya',
        'age' => 25,
    ],
    1 => [
        'user_id' => 5,
        'name' => 'Petya',
        'age' => 30,
    ],
    2 => [
        'user_id' => 8,
        'name' => 'Grisha',
        'age' => 25,
    ],
];

В случае использования просто "assoc" без дополнительных параметров, получается обычный порядковый массив. Дополнительным параметром можно указать имя столбца, значение из которого будет использоваться в качестве ключа массива. Например, формат "assoc:user_id" вернёт следующий результат:

[
    1 => [
        'user_id' => 1,
        'name' => 'Vasya',
        'age' => 25,
    ],
    5 => [
        'user_id' => 5,
        'name' => 'Petya',
        'age' => 30,
    ],
    8 => [
        'user_id' => 8,
        'name' => 'Grisha',
        'age' => 25,
    ],
);

а "assoc:age" следующий:

[
    25 => [
        'user_id' => 8,
        'name' => 'Grisha',
        'age' => 25,
    ],
    30 => [
        'user_id' => 5,
        'name' => 'Petya',
        'age' => 30,
    ],
];

Более поздние записи перекрывают более ранние с теми же ключами.

numerics, numerics:{$key}

Аналогичный формат, только запись представляется не ассоциативным массивом, а порядковым. Подобно перебору с mysql_fetch_row().

objects, objects:{$key}

А этот формат аналогичен перебору с mysql_fetch_object(): каждая запись представляется объектом.

foreach ($db->query('SELECT * FROM `users`')->objects() as $user) {
    echo 'Username: '.$user->name."\n";
}

col

Выборка по одному столбцу. В результате: порядковый массив с элементами - значениями заданного столбца.

$usersIds = $db->query('SELECT `user_id` FROM `users`')->col();
var_dump($usersIds); // list of all IDs

$tables = $db->query('SHOW TABLES');
var_dump($tables); // list of all tables

vars

Выборка по двум столбцам, значение первого становится ключом, второго - элементом массива.

Допустим существует таблица "параметров пользователя":

`name`   | `value`  | `user_id`
"age"    | "25"     | 1
"sex"    | "male"   | 1
"status" | "loser"  | 1
"age"    | "30"     | 2
"sex"    | "male"   | 2
...

Следующий запрос выберет все параметры заданного пользователя в виде "параметр" => "значение":

$params = $db('SELECT `name`,`value` FROM `users` WHERE `user_id`=?i', [$userId])->vars();
echo 'Age: '.$params['age'];
echo 'Sex: '.$params['sex'];
echo 'Status: '.$params['status'];

Если в выборке один столбец: он становится и ключом и значением.

Итераторы

  • iassoc, iassoc:{$key}
  • inumerics, inumerics:{$key}
  • iobjects, iobjects:{$key}
  • icol
  • ivars

Форматы, аналогичные вышеописанным, только вместо массива возвращается объект, реализующий интерфейс Iterator. То есть его можно также перебирать, как и массивы.

$users = $db->query('SELECT * FROM `users`')->iassoc();
foreach ($users as $user) {
    echo 'Another user:';
    var_dump($user);
}

Итераторы могут пригодится при выборке очень большого количества данных. Сначала выбирать все эти данные в массив, а потом перебирать уже его, может быть слишком накладным.

Замечание: в текущей версии goDB ещё не реализованы нормально unbuffered-запросы, поэтому толку от итераторов не так много.

При переборе итераторов могут быть некоторые отличия от соответствующих массивов. При использовании vars или assoc:{$key} в выборке могут встречаться записи с одинаковыми ключами и в массиве останется только последняя из них. При использовании же итераторов, все записи пройдут через foreach.

Выборка (SELECT) одной строки

Выборка одной строки, это обычно выборка по ID. Все форматы данной группы возвращают первую строку выборки, если же выборка пуста, то возвращают NULL.

row

Одна строка в виде ассоциативного массива полей.

$user = $db->query('SELECT * FROM `users` WHERE `user_id`=?i', [$_GET['id']])->row();
if ($user) {
    echo 'User params:';
    print_r($user);
    /*
    [
        'user_id' => 5,
        'name' => 'Vasya',
        'age' => 25,
    ]
    */
} else {
    echo 'User not found';
}

numeric

Тоже самое, только не ассоциативный, а порядковый массив полей.

object

Одна строка, представленная в виде объекта, чьи поля - поля записи.

$user = $db->query('SELECT * FROM `users` WHERE `user_id`=?i', [$_GET['id']])->object();
if ($user) {
    echo 'Username: '.$user->name;
}

el

Выборка по одному значению. Первый столбец первой строки в выборке, или NULL, если выборка пустая.

$email = $db->query('SELECT `email` FROM `users` WHERE `user_id`=?i', [$_GET['id']])->el();
if ($email) {
    echo 'User e-mail: '.$email;
} else {
    echo 'User not found';
}

bool

Как el, только результат приводится к TRUE/FALSE. Обычно используется для выборки по столбцу с типом "BOOL". При этом NULL также приводится к FALSE.

Другие форматы

num

Возвращает количество строк в полученной выборке.

Помните, что обычно существуют лучшие способы узнать количество строк, соответствующих условию, чем выбрать их все и посчитать.

id

Возвращает последний автоинкремент (или его аналог). Используется вместе с операцией вставки.

$set = [
    'name' => 'Newcomer',
    'age' => 27,
    'status' => 'new',
];
$userId = $db->query('INSERT INTO `users` SET ?set', [$set])->id();
echo 'New user ID: #'.$userId;

ar

Количество затронутых запросом столбцов.

$ar = $db->query('DELETE FROM `users` WHERE `status`=?', ['loser'])->ar();
echo 'Remove '.$ar.' losers';
cursor Возвращает внутреннее представление курсора, зависящее от адаптера.

Для адаптера mysql (являющегося надстройкой над php_mysqli), это будет mysqli_result.

Используется для более тонкой обработки.

Result - итератор

Объект результата (интерфейс go\DB\Result) реализует интерфейс IteratorAggregate и в качестве итератора возвращает объект аналогичный формату iassoc.

То есть можно делать так:

foreach ($db->query('SELECT * FROM `table`') as $row) {
    var_dump($row);
}

Ошибки при разборе результата

Первая ошибка - использование неизвестного формата разбора. При попытке вызвать неизвестный метод Result получится обыкновенная PHP-ошибка. При использовании же неизвестного формата в качестве аргумента query() выбрасывается исключение UnknownFetch.

Вторая ошибка и исключение UnexpectedFetch: неожиданный формат для данного типа результата. Это попытка разобрать результат, не являющийся результатом выборки (курсором), как результат выборки. В примере - попытка представить результат INSERT в виде ассоциативного массива.

$db->query('INSERT INTO `table` SET `a`=?', [5])->assoc();
Clone this wiki locally