Запросы
- Основы запросов
- Работа с префиксами баз данных вручную
- Защита идентификаторов
- Экранирование запросов
- Связывание запросов
- Обработка ошибок
- Подготовленные запросы
- Работа с объектами запросов
Основы запросов
Обычные запросы
Для отправки запроса используйте функцию query:
$db = db_connect();
$db->query('YOUR QUERY HERE');
Функция query() возвращает объект результата базы данных при выполнении запросов типа «чтение», который вы можете использовать для отображения результатов. При выполнении запросов типа «запись» она просто возвращает true или false в зависимости от успеха или неудачи. При получении данных вы обычно присваиваете запрос своей переменной, например так:
$query = $db->query('YOUR QUERY HERE');
Упрощенные запросы
Метод simpleQuery — это упрощенная версия метода $db->query(). Он НЕ возвращает набор результатов базы данных, не устанавливает таймер запроса, не компилирует данные связывания и не сохраняет ваш запрос для отладки. Он просто позволяет отправлять запрос. Большинство пользователей редко используют эту функцию.
Она возвращает то, что функция «execute» драйвера базы данных возвращает. Обычно это true/false при успехе или неудаче для запросов типа запись, таких как INSERT, DELETE или UPDATE (для чего она и предназначена), и ресурс/объект при успехе для запросов с результатами, которые можно получить.
if ($db->simpleQuery('YOUR QUERY')) {
echo "Success!";
} else {
echo "Query failed!";
}
Примечание
Функция PostgreSQL pg_exec() (например) всегда возвращает ресурс при успехе, даже для запросов типа запись. Поэтому имейте это в виду, если вам нужна булева величина.
Работа с префиксами баз данных вручную
Если вы настроите префикс базы данных и хотите добавить его к имени таблицы для использования в запросе SQL, например, то вы можете использовать следующее:
$db->prefixTable('tablename'); // outputs prefix_tablename
Если по какой-либо причине вам нужно изменить префикс программно, без необходимости создания нового соединения, вы можете использовать этот метод:
$db->setPrefix('newprefix_');
$db->prefixTable('tablename'); // outputs newprefix_tablename
Вы можете получить текущий префикс в любое время с помощью этого метода:
$DBPrefix = $db->getPrefix();
Защита идентификаторов
Во многих базах данных рекомендуется защищать имена таблиц и полей — например, с помощью обратных кавычек в MySQL. Запросы Query Builder автоматически защищаются, но если вам нужно вручную защитить идентификатор, вы можете использовать:
$db->protectIdentifiers('table_name');
Важно
Хотя Query Builder постарается правильно процитировать все имена полей и таблиц, которые вы ему предоставите. Обратите внимание, что он НЕ предназначен для работы с произвольными пользовательскими данными. НЕ передавайте ему необработанные пользовательские данные.
Эта функция также добавит префикс таблицы к вашей таблице, предполагая, что у вас указан префикс в файле конфигурации базы данных. Для включения префикса установите значение true (булево) через второй параметр:
$db->protectIdentifiers('table_name', true);
Экранирование запросов
Очень хорошая практика безопасности — экранировать данные перед отправкой их в базу данных. CodeIgniter предоставляет три метода для этого:
-
$db->escape() Эта функция определяет тип данных, чтобы экранировать только строковые данные. Она также автоматически добавляет одинарные кавычки вокруг данных, поэтому вам не нужно:
$sql = "INSERT INTO table (title) VALUES(" . $db->escape($title) . ")"; -
$db->escapeString() Эта функция экранирует данные, переданные ей, независимо от типа. В большинстве случаев вы будете использовать вышеприведенную функцию, а не эту. Используйте функцию так:
$sql = "INSERT INTO table (title) VALUES('" . $db->escapeString($title) . "')"; - $db->escapeLikeString() Этот метод следует использовать, когда строки должны использоваться в условиях LIKE, чтобы символы подстановки LIKE (‘%’, ‘_’) в строке также были должным образом экранированы.
$search = '20% raise'; $sql = "SELECT id FROM table WHERE column LIKE '%" . $db->escapeLikeString($search) . "%' ESCAPE '!'";
Важно
Метод escapeLikeString() использует ‘!’ (восклицательный знак) для экранирования специальных символов для условий LIKE. Поскольку этот метод экранирует частичные строки, которые вы сами обернули в кавычки, он не может автоматически добавить условие ESCAPE '!', поэтому вам нужно сделать это вручную.
Связывание запросов
Связывание запросов позволяет упростить синтаксис запроса, позволяя системе собирать запросы за вас. Рассмотрим следующий пример:
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?"; $db->query($sql, [3, 'live', 'Rick']);
Знаки вопроса в запросе автоматически заменяются значениями в массиве во втором параметре функции query.
Связывание также работает с массивами, которые будут преобразовываться в наборы IN:
$sql = "SELECT * FROM some_table WHERE id IN ? AND status = ? AND author = ?"; $db->query($sql, [[3, 6], 'live', 'Rick']);
Результат запроса будет таким:
SELECT * FROM some_table WHERE id IN (3,6) AND status = 'live' AND author = 'Rick'
Дополнительное преимущество использования связывания заключается в том, что значения автоматически экранируются, что делает запросы безопаснее. Вам не нужно помнить, как вручную экранировать данные — движок делает это автоматически.
Именованные связывания
Вместо использования знака вопроса для обозначения места привязанных значений, вы можете назначить имена связям, что позволяет ключам переданных значений соответствовать плейсхолдерам в запросе:
$sql = "SELECT * FROM some_table WHERE id = :id: AND status = :status: AND author = :name:";
$db->query($sql, [
'id' => 3,
'status' => 'live',
'name' => 'Rick',
]);
Примечание
Каждое имя в запросе ДОЛЖНО быть заключено в двоеточия.
Обработка ошибок
$db->error();
Если вам нужно получить последнюю ошибку, которая произошла, метод error() вернет массив, содержащий его код и сообщение. Вот быстрый пример:
if ( ! $db->simpleQuery('SELECT `example_field` FROM `example_table`')) {
$error = $db->error(); // Has keys 'code' and 'message'
}
Подготовленные запросы
Большинство баз данных поддерживают подготовленные инструкции, которые позволяют подготовить запрос один раз и затем выполнить этот запрос несколько раз с новыми наборами данных. Это исключает возможность SQL-инъекций, так как данные передаются в базу данных в другом формате, отличном от самого запроса. Когда вам нужно выполнить один и тот же запрос несколько раз, это может быть намного быстрее. Однако, использование его для каждого запроса может значительно повлиять на производительность, так как вы вызываете базу данных вдвое чаще. Поскольку Query Builder и соединения с базами данных уже обрабатывают экранирование данных за вас, вопрос безопасности уже решен. Однако, в некоторых случаях вам нужно будет оптимизировать запрос, выполнив подготовленный запрос.
Подготовка запроса
Это можно легко сделать с помощью метода prepare(). Он принимает один параметр, который представляет собой замыкание, возвращающее объект запроса. Объекты запроса автоматически генерируются для запросов типа «окончательный», включая insert, update, delete, replace и get. Самый простой способ сделать это — использовать Query Builder для выполнения запроса. Запрос не выполняется, и значения не важны, поскольку они никогда не применяются, а вместо этого служат плейсхолдерами. Это возвращает объект PreparedQuery:
$pQuery = $db->prepare(function ($db) {
return $db->table('user')->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US'
]);
});
Если вы не хотите использовать Query Builder, вы можете создать объект Query вручную, используя знаки вопроса для плейсхолдеров значений:
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(function ($db) {
$sql = "INSERT INTO user (name, email, country) VALUES (?, ?, ?)";
return (new Query($db))->setQuery($sql);
});
Если база данных требует, чтобы массив с параметрами передавался ей во время подготовки запроса, вы можете передать этот массив во втором параметре:
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(function ($db) {
$sql = "INSERT INTO user (name, email, country) VALUES (?, ?, ?)";
return (new Query($db))->setQuery($sql);
}, $options);
Выполнение запроса
После получения подготовленного запроса вы можете использовать метод execute() для фактического выполнения запроса. Вы можете передавать любое количество переменных в параметрах запроса. Количество параметров, которые вы передаете, должно совпадать с количеством плейсхолдеров в запросе. Они также должны передаваться в том же порядке, что и плейсхолдеры в исходном запросе:
// Prepare the Query
$pQuery = $db->prepare(function ($db) {
return $db->table('user')->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US'
]);
});
// Collect the Data
$name = 'John Doe';
$email = 'j.doe@example.com';
$country = 'US';
// Run the Query
$results = $pQuery->execute($name, $email, $country);
Это возвращает стандартный набор результатов.
Другие методы
В дополнение к этим двум основным методам, объект подготовленного запроса также имеет следующие методы:
close()
Хотя PHP хорошо справляется с закрытием всех открытых запросов к базе данных, всегда хорошая идея закрыть подготовленный запрос, когда вы с ним закончили:
$pQuery->close();
getQueryString()
Возвращает подготовленный запрос в виде строки.
hasError()
Возвращает булево значение true/false, если последний вызов execute() создал какие-либо ошибки.
getErrorCode() getErrorMessage()
Если были обнаружены какие-либо ошибки, с помощью этих методов можно получить код и строку ошибки.
Работа с объектами запросов
Внутренне все запросы обрабатываются и хранятся как экземпляры CodeIgniter\Database\Query. Этот класс отвечает за связывание параметров, иначе подготовку запроса и хранение данных о производительности запроса.
getLastQuery()
Для получения последнего объекта запроса используйте метод getLastQuery():
$query = $db->getLastQuery(); echo (string) $query;
Класс запроса
Каждый объект запроса хранит несколько фрагментов информации о самом запросе. Это используется, в частности, функцией Timeline, но также доступно и для вашего использования.
getQuery()
Возвращает окончательный запрос после всех обработок. Это точный запрос, который был отправлен в базу данных:
$sql = $query->getQuery();
Это то же самое значение можно получить, применив к объекту запроса преобразование в строку:
$sql = (string) $query;
getOriginalQuery()
Возвращает исходный SQL, который был передан в объект. В нем не будет никаких привязок, или заменённых префиксов и т.д.:
$sql = $query->getOriginalQuery();
hasError()
Если при выполнении этого запроса возникла ошибка, этот метод вернет true:
if ($query->hasError()) {
echo 'Code: ' . $query->getErrorCode();
echo 'Error: ' . $query->getErrorMessage();
}
isWriteType()
Возвращает true, если запрос был определён как запрос типа записи (т.е., INSERT, UPDATE, DELETE и т.д.):
if ($query->isWriteType()) {
// ... do something
}
swapPrefix()
Заменяет один префикс таблицы другим значением в окончательном SQL. Первый параметр — оригинальный префикс, который нужно заменить, а второй — значением, на которое его нужно заменить:
$sql = $query->swapPrefix('ci3_', 'ci4_');
getStartTime()
Возвращает время выполнения запроса в секундах с микросекундами:
$microtime = $query->getStartTime();
getDuration()
Возвращает значение с плавающей точкой с длительностью запроса в секундах с микросекундами:
$microtime = $query->getDuration();
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/user_guide/database/queries.html