Выполнение запроса

Запрос выполняется с помощью метода query():


mixed $db->query(string $pattern [, array $data [, string $fetch [, string $prefix]);			
			

Это один из немногих методов mysqli, переопределенный в goDB. Впрочем, вы можете использовать его по старинке без каких либо различий:


$result = $db->query("select * from `table` where `id`=10");
			

Единственное различие при таком формате вызова: при возникновении ошибки, она не тихо оседает в каком-то внутреннем поле, а вываливается в виде исключения.

Основные различия начинаются при указании второго параметра. В этом случае $pattern рассматривается как шаблон запроса, а $data, как массив входных данных. На основании этих двух аргументов и формируется запрос.

Note: в PHP 5.3 и выше, можно не вызывать метод query а использовать вызов самого объекта:


$result = $db($pattern, $data, $fetch);
			

Формат шаблона запроса

Шаблон запроса, представляет собой «почти SQL», только место вставки очередного данного помечается особой последовательностью: плейсхолдером. Пример:


$pattern = 'INSERT INTO `table` (`a`,`b`,`c`) VALUES (?, ?, ?)';
$data    = array('раз', '2 ("два")', 'три');
$result  = $db->query($pattern, $data);
			

В результате будет выполнен запрос:


INSERT INTO `table` (`a`,`b`,`c`) VALUES ("раз", "2 (\"два\")", "три")
			

Как видно, данные из массива последовательно вставились в шаблон на место знаков «?» (плейсхолдеров). При вставке данные экранируются и заключаются в кавычки.

Список плейсхолдеров

Для вставке данных можно использовать отнюдь не только простой ?. Полный список доступных плейсхолдеров и поддерживаемых форматов данных приведён ниже.

Большинство плейсхолдеров имеют, как краткий формат (?v), так и "длинный" (?values). Перечеркнутые плейсхолдеры не рекомендуются к использованию и оставлены для обратной совместимости.

?
?string

Общий вид данных, обрабатывается как строка: специальные символы экранируются, вся строка заключается в кавычки.

Пример см. выше.

?n
?null

$pattern = 'INSERT INTO `table` VALUES (?n, ?n, ?n)';
$data    = array('qwe', null, 'rty');
$result  = $db->query($pattern, $data);
 

Итог:


INSERT INTO `table` VALUES ("qwe", NULL, "rty");
 

Единственное отличие от ?: null из данных вставляется, как NULL (в первом же случае, как пустая строка).

Подобные два варианта имеют место также для ?i. Плейсхолдеры же ?list, ?set и подобные им, всегда вставляют null-данные, как NULL.

?i
?int

Вставка числа:


$pattern = 'INSERT INTO `table` VALUES (?i, ?i, ?, ?i, ?in)';
$data    = array('12', '34x56', '78x90', null, null);
$result  = $db->query($pattern, $data);
 

Итог:


INSERT INTO `table` VALUES (12, 34, "78x90", 0, NULL);
 

Очередное данное вставляется, как число. Если там строка — приводится к числу.

Несмотря на название, обрабатывает не только int, но и float.

Предотвращение SQL-инъекций:


$pattern = 'SELECT * FROM `table` WHERE `id`=?i';
$data    = array($_GET['id']);
$result  = $db->query($pattern, $data);
 

В принципе, простой плейсхолдер ? тоже бы подошел (mysql обработает строку как надо для числового поля), но ?i добавляет семантики, не надеется на то, что база сделает что-то за него и удобен и в других случаях.

?in
?ni
?int-null

Аналогичен ?i за исключением того, что null при ?i превращается в 0, а здесь в NULL.

?bool

Вставка значения для столбца типа BOOL.


$banned  = true;
$pattern = 'UPDATE `users` SET `banned`=?bool; WHERE `user_id`=?i';
$data    = array($banned, $userId);
$result  = $db->query($pattern, $data);
 

Несмотря на то, что в mysql BOOL на самом деле представлен числом, ?bool имеет отличия от ?int:

  1. Строка «qwe» для ?int приведётся к 0 (не число), а для ?bool к 1 (непустая строка).
  2. Все числа не равные 0, ?bool приведёт к 1.
  3. Ну и просто семантика никогда не лишняя.
?l
?list
?a

Список значений в виде порядкового массива:


$names   = array('Вася', 'Петя', 'Миша', 'Гриша');
$pattern = 'SELECT * FROM `table` WHERE `id`>?i AND `name` IN (?list)';
$data    = array(11, $names);
$result  = $db->query($pattern, $data);
 

Итог:


SELECT * FROM `table` WHERE `id`>11 AND `name` IN ("Вася","Петя","Миша","Гриша")
 

Все элементы массива обрабатываются как строки (могут также содержать null).

?li
?list-int
?ai
?ia

Аналог ?list, только все элементы обрабатываются как числа:


$ids     = array(1, 2, 3, null, 5);
$pattern = 'SELECT * FROM `table` WHERE `id` IN (?li)';
$data    = array($ids);
$result  = $db->query($pattern, $data);
 

Запрос:


SELECT * FROM `table` WHERE `id` IN (1, 2, 3, NULL, 5)
 
?s
?set

Ассоциативный массив "столбец"=>"значение" (для секций типа SET):


$cols = array(
	'one'   => 1,
	'two'   => '2 ("два")',
	'three' => null,
);
$pattern = 'INSERT INTO `table` SET ?set';
$data    = array($cols);
$result  = $db->query($pattern, $data);
 

Запрос:


INSERT INTO `table` SET `one`=1,`two`="Два",`three`=NULL;
 
?v
?values

Двумерный массив — список из нескольких строк:


$values = array(
	array(1, 2, 3),
	array(4, 5, 6),
	array(7, 8, 9),
);
$pattern = 'INSERT INTO `table` (`a`,`b`,`c`) VALUES ?v';
$data    = array($values);
$result  = $db->query($pattern, $data);
 

Запрос:


INSERT INTO `table` (`a`,`b`,`c`) VALUES (1,2,3),(4,5,6),(7,8,9)
 
?t
?table

Вставка имени таблицы:


define('T_USERS', 'users');
$pattern = 'SELECT * FROM ?t WHERE `user_id`=?i';
$data    = array(T_USERS, 11);
$result  = $db->query($pattern, $data);
 

Запрос:


SELECT * FROM `users` WHERE `user_id`=11
 

Как видно, первое применение: указание таблицы, чьё имя хранится где-то.

Плюс ещё удобная фишка: использование префиксов.


define('T_USERS', 'users');
$db->setPrefix('test_');
$pattern = 'SELECT * FROM ?t WHERE `user_id`=?i';
$data    = array(T_USERS, 11);
$result  = $db->query($pattern, $data);
 

Запрос:


SELECT * FROM `test_users` WHERE `user_id`=11
 

То есть, если мы хотим использовать префиксы для таблиц, мы можем один раз в начале вызвать setPrefix() и не думать о них больше.

Также префикс можно указать в сразу конфигурации базы (см. раздел про подключение).

Ещё префикс можно указывать непосредственно для одного запроса в соответствующем аргументе метода query().


$prefix = 't_';
$result = $db->query($pattern, $data, $fetch, $prefix);
 

Ну и если префиксы использовать хочется, а хранить имена таблиц отдельно нет, есть дополнительный синтаксис:


$db->query('SELECT * FROM {users}');
 

{users} будет заменено на имя таблицы `users`, с использованием, если нужно, префикса.

?c
?col

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

Дополнительно возможен формат array('таблица', 'столбец').


$db->setPrefix('test_');
$pattern = 'SELECT ... WHERE ?c=?i AND ?c=?c';
$data    = array('a', 10, 'b', array('table', 'a'));
$result  = $db->query($pattern, $data);
 

Запрос:


SELECT ... WHERE `a`=10 AND `b`=`test_table`.`a`
 
?e
?escape

Вставка части строки (экранируются спецсимволы):


$search  = 'Вася';
$pattern = 'SELECT * FROM `table` WHERE `name` LIKE "?e%";
$data    = array($search);
$result  = $db->query($pattern, $data);
 

Запрос:


SELECT * FROM `table` WHERE `name` LIKE "Вася%"
 
?q
?query

Вставка части запроса.


if ($condition) {
	$where = '`field`=1';
} else {
	$where = '`field`=2';
}
$pattern = 'SELECT * FROM `table` WHERE ?q LIMIT ?i';
$data    = array($where, 10);
$result  = $db->query($pattern, $data);
 

Запрос:


SELECT * FROM `table` WHERE `field`=1 LIMIT 10
 

В отличии от варианта $pattern = 'SELECT * FROM `table` WHERE '.$where.' LIMIT ?i', при использовании ?query $where не станет частью шаблона и не будет разбираться на предмет плейсхолдеров.

?;
?set;
...

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

??

Для вставки напрямую знака вопроса, удвойте его.

В случае, если количество плейсхолдеров не совпадает с количеством входных данных (размером массива $data), а также, если указан неизвестный плейсхолдер, генерируются исключения.

Если входных данных нет, вместо пустого массива можно указать NULL: $db->query($pattern, null, 'el');.

© Григорьев Олег aka vasa_c, 2006—2010