Основы работы с базами данных
# Введение
В OctoberCMS можно настроить соединение с БД и выполнять запросы чрезвычайно просто для различных «движков» БД, будь то сырой SQL, гибкий строитель запросов или Active Record. Работа с таблицами и начальными данными описана в разделе Структура базы данных.
# Настройка
Настройки БД вашего приложения хранятся в файле config/database.php
. Здесь вы можете указать все используемые вами соединения, а также задать соединение по умолчанию. Примеры настройки всех возможных видов подключений находятся в этом же файле.
# Чтение / Запись
Иногда вам может понадобиться использовать разные подключения к базе данных: одно для запросов SELECT, а другое для запросов INSERT, UPDATE и DELETE. Сделать это очень просто! При этом всегда будет использоваться соответствующее соединение вне зависимости от типа запроса.
Чтобы увидеть, как должны быть настроены соединения чтения/записи, давайте рассмотрим этот пример:
'mysql' => [
'read' => [
'host' => '192.168.1.1',
],
'write' => [
'host' => '196.168.1.2'
],
'driver' => 'mysql',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
Обратите внимание на то, что в массив с настройками были добавлены два элемента: read
и write
. Оба элемента представляют собой массив с одним элементом 'host'. Остальные параметры БД для подключений чтения/записи будут заимствованы из основного массива mysql
.
Поэтому размещать элементы в массивах для этих подключений стоит, только если вы хотите переопределить их значения из основного массива. Таким образом, в этом случае, 192.168.1.1
будет использоваться как подключение «чтения», а 192.168.1.2
— как подключение «записи». Учётные данные для БД, префикс, набор символов, и все другие параметры основного массива mysql
будут использованы для обоих подключений.
# Выполнение сырых SQL-запросов
Когда вы настроили соединение с базой данных, вы можете выполнять запросы, используя фасад Db
. Этот фасад имеет методы для каждого типа запроса: select
, update
, insert
, delete
и statement
.
# Выполнение запроса SELECT
Вы можете использовать метод select
фасада Db
, чтобы выполнить базовый запрос:
$users = Db::select('select * from users where active = ?', [1]);
Первый аргумент метода select
— сырой SQL-запрос, второй — любые связки параметров для прикрепления к запросу. Обычно это значения ограничений условия where. Привязка параметров обеспечивает защиту от SQL-инъекций.
Метод select
всегда возвращает массив результатов. Каждый результат в массиве — объект PHP stdClass
, что позволяет вам обращаться к значениям результатов:
foreach ($users as $user) {
echo $user->name;
}
# Использование привязки имён
Вместо использования знака вопроса ?
для обозначения привязки параметров, Вы можете выполнить запрос, используя привязку по имени:
$results = Db::select('select * from users where id = :id', ['id' => 1]);
# Выполнение запроса INSERT
Чтобы выполнить запрос insert
, можно использовать метод insert
фасада DB. Как и select
, данный метод принимает сырой SQL-запрос первым аргументом, а вторым — привязки:
Db::insert('insert into users (id, name) values (?, ?)', [1, 'Joe']);
# Выполнение запроса UPDATE
Для обновления существующих записей в БД используется метод update
, который возвращает количество изменённых записей:
$affected = Db::update('update users set votes = 100 where name = ?', ['John']);
# Выполнение запроса DELETE
Для удаления записей из БД используется метод delete
, который возвращает количество удалённых записей:
$deleted = Db::delete('delete from users');
# Выполнение запроса общего типа
Иногда запрос к БД не должен возвращать каких-либо значений. Для операций такого типа можно использовать метод statement
фасада Db
:
Db::statement('drop table users');
# Использование нескольких соединений с БД
При использовании нескольких соединений с БД вы можете получить доступ к каждому из них через метод connection
фасада Db
. Передаваемое в этот метод имя name
должно соответствовать одному из перечисленных в файле config/database.php
соединений:
$users = Db::connection('foo')->select(...);
Вы также можете получить низкоуровневый объект PDO для этого подключения методом getPdo
:
$pdo = Db::connection()->getPdo();
# Транзакции
Для выполнения набора запросов внутри одной транзакции вы можете использовать метод transaction
фасада Db
. Если в замыкании транзакции произойдёт исключение, она автоматически откатится. А если замыкание выполнится успешно, транзакция автоматически применится к БД. Вам не стоит переживать об этом при использовании метода transaction
:
Db::transaction(function () {
Db::table('users')->update(['votes' => 1]);
Db::table('posts')->delete();
});
# Ручное использование транзакций
Если вы хотите запустить транзакцию вручную и иметь полный контроль над её откатом и применением, используйте метод beginTransaction
фасада Db
:
Db::beginTransaction();
Вы можете откатить транзакцию методом rollback
:
Db::rollBack();
Наконец, вы можете применить транзакцию методом commit
:
Db::commit();
Примечание: Методы фасада DB для транзакций также контролируют транзакции построителя запросов и запросов модели.
# Прослушивание событий запросов
If you would like to receive each SQL query executed by your application, you may use the listen
method. This method is useful for logging queries or debugging.
Db::listen(function($sql, $bindings, $time) {
//
});
Just like event registration, you may register your query listener in the boot()
method of a Plugin registration file. Alternatively, plugins can supply a file named init.php in the plugin directory that you can use to place this logic.
# Журнал запросов
При включенном логировании OctoberCMS записывает все SQL-запросы, выполненные в рамках текущего запроса страницы. Для подключения журнала вы можете использовать метод enableQueryLog
:
Db::connection()->enableQueryLog();
Чтобы получить массив выполненных запросов, вы можете использовать метод getQueryLog
:
$queries = Db::getQueryLog();
Однако, в некоторых случаях — например, при вставке большого набора записей — это может быть слишком ресурсозатратно. Чтобы отключить логирование, используйте метод disableQueryLog
:
Db::connection()->disableQueryLog();
Примечание: Для быстрой отладки приложения лучше использовать метод
trace_sql()
.