Введение
В Laravel можно чрезвычайно просто взаимодействовать с БД на различных «движках», будь то сырой SQL, гибкий построитель запросов или Eloquent ORM. На данный момент Laravel поддерживает четыре системы баз данных:
- MySQL
- Postgres
- SQLite
- SQL Server
Настройка
Настройки работы с БД хранятся в файле config/database.php. Здесь вы можете указать все используемые вами соединения к БД, а также задать соединение по умолчанию. Примеры настройки большинства поддерживаемых видов подключений находятся в этом же файле.
По умолчанию образец настройки окружения Laravel подготовлен для использования с Laravel Homestead — удобной виртуальной машиной для Laravel-разработки на вашей локальной машине. Разумеется, вы можете изменить эти настройки для работы с вашей локальной БД.
После создания новой базы данных SQLite при помощи команды shtouch database/database.sqlite
, вы можете легко настроить переменные вашей среды для этой новой базы данных, используя её абсолютный путь:
confDB_CONNECTION=sqlite DB_DATABASE=/absolute/path/to/database.sqlite
Laravel поддерживает работу с SQL Server из коробки, надо лишь добавить настройку подключения к БД в ваш файл настроек config/database.php:
conf'sqlsrv' => [ 'driver' => 'sqlsrv', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', ],
Соединения для чтения и записи
Иногда вам может понадобиться использовать разные подключения к базе данных: одно для запросов SELECT, а другое для запросов INSERT, UPDATE и DELETE. В Laravel это делается очень просто, и всегда будет использоваться соответствующее соединение, используете ли вы сырые запросы, построитель запросов или Eloquent ORM.
Чтобы увидеть, как должны быть настроены соединения чтения/записи, давайте посмотрим на этот пример:
'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' => '',
],
Обратите внимание, что в массив настроек были добавлены два элемента: sql'read'
и sql'write'
. Оба элемента представляют собой массив с одним элементом sql'host'
. Остальные параметры БД для подключений чтения/записи будут заимствованы из основного массива sql'mysql'
.
Вам стоит размещать элементы в массивах PHPread
и PHPwrite
, только если вы хотите переопределить их значения из основного массива. Таким образом, в этом случае, 192.168.1.1 будет использоваться как хост для подключения «чтения», а 192.168.1.2 — для подключения «записи». Учётные данные для БД, префикс, набор символов, и все другие параметры основного массива sql'mysql'
будут использованы для обоих подключений.
Использование нескольких соединений с БД
При использовании нескольких соединений с БД вы можете получить доступ к каждому из них через метод PHPconnection()
фасада DB. Передаваемое в этот метод имя name должно соответствовать одному из перечисленных в файле config/database.php соединений:
$users = DB::connection('foo')->select(...);
Вы также можете получить низкоуровневый объект PDO для этого подключения методом PHPgetPdo()
:
$pdo = DB::connection()->getPdo();
Выполнение сырых SQL-запросов
Когда вы настроили соединение с базой данных, вы можете выполнять запросы, используя фасад DB. Этот фасад имеет методы для каждого типа запроса: select, update, insert, delete и statement.
Чтобы выполнить базовый запрос, можно использовать метод PHPselect()
фасада DB:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
//для версии 5.2 и ранее:
//use DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Показать список всех пользователей приложения.
*
* @return Response
*/
public function index()
{
$users = DB::select('select * from users where active = ?', [1]);
return view('user.index', ['users' => $users]);
}
}
Первый аргумент метода PHPselect()
— сырой SQL-запрос, второй — любые связки параметров для прикрепления к запросу. Обычно это значения ограничений условия where. Привязка параметров обеспечивает защиту от SQL-инъекций.
Метод PHPselect()
всегда возвращает массив результатов. Каждый результат в массиве — объект PHP StdClass, что позволяет вам обращаться к значениям результатов:
foreach ($users as $user) {
echo $user->name;
}
Вместо использования знака вопроса ? для обозначения привязки параметров, вы можете выполнить запрос, используя привязку по имени:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
Чтобы выполнить запрос insert, можно использовать метод PHPinsert()
фасада DB. Как и PHPselect()
, данный метод принимает сырой SQL-запрос первым аргументом, а вторым — привязки:
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
Для обновления существующих записей в БД используется метод PHPupdate()
, который возвращает количество изменённых записей:
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
Для удаления записей из БД используется метод PHPdelete()
, который возвращает количество изменённых записей:
$deleted = DB::delete('delete from users');
Выполнение запроса общего типа
Некоторые запросы к БД не возвращают никаких значений. Для операций такого типа можно использовать метод PHPstatement()
фасада DB:
DB::statement('drop table users');
Прослушивание событий запросов
Если вы хотите получать каждый выполненный вашим приложением SQL-запрос, используйте метод PHPlisten()
. Этот метод полезен для журналирования запросов и отладки. Вы можете зарегистрировать свой слушатель запросов в сервис-провайдере:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
//для версии 5.2 и ранее:
//use DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Загрузка всех сервисов приложения.
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
//В этом примере из документации по версии 5.1 и ранее было:
//DB::listen(function($sql, $bindings, $time) {
// //
});
}
/**
* Регистрация сервис-провайдера.
*
* @return void
*/
public function register()
{
//
}
}
Транзакции
Для выполнения набора запросов внутри одной транзакции вы можете использовать метод PHPtransaction()
фасада DB. Если в замыкании транзакции произойдёт исключение, она автоматически откатится. А если замыкание выполнится успешно, транзакция автоматически применится к БД. Вам не стоит переживать об этом при использовании метода PHPtransaction()
:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
добавлено в 5.3 ()
Метод PHPtransaction()
принимает второй необязательный аргумент, с помощью которого задаётся число повторных попыток транзакции при возникновении взаимной блокировки (англ. deadlock). После истечения этих попыток будет выброшено исключение:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
}, 5);
Ручное использование транзакций
Если вы хотите запустить транзакцию вручную и иметь полный контроль над её откатом и применением, используйте метод PHPbeginTransaction()
фасада DB:
DB::beginTransaction();
Вы можете откатить транзакцию методом PHProllback()
:
DB::rollback();
Наконец, вы можете применить транзакцию методом PHPcommit()
:
DB::commit();
Методы фасада DB для транзакций также контролируют транзакции построителя запросов и Eloquent ORM.
Транзакция — особое состояние БД, в котором выполняемые запросы либо все вместе успешно завершаются, либо (в случае ошибки) все их изменения откатываются. Это позволяет поддерживать целостность внутренней структуры данных. К примеру, если вы вставляете запись о заказе, а затем в отдельную таблицу добавляете товары, то при неуспешном выполнении скрипта (в том числе падения веб-сервера, ошибки в запросе и пр.) СУБД автоматически удалит запись о заказе и все товары, которые вы успели добавить — прим. пер.
добавлено в 5.0 ()
Иногда вам может понадобиться переподключиться и вы можете сделать это так:
DB::reconnect('foo');
Если вам нужно отключиться от данной БД из-за превышения основного предела экземпляров PDO max_connections, используйте метод PHPdisconnect()
:
DB::disconnect('foo');
Журнал запросов
По умолчанию Laravel записывает все SQL-запросы, выполненные в рамках текущего запроса страницы. Однако в некоторых случаях — например, при вставке большого набора записей — это может быть слишком ресурсозатратно. Для подключения журнала вы можете использовать метод PHPenableQueryLog()
:
DB::connection()->enableQueryLog();
Чтобы получить массив выполненных запросов, вы можете использовать метод PHPgetQueryLog()
:
$queries = DB::getQueryLog();
Комментарии (2)
Файла app/config/database.php не существует, но есть config/database.php
Жаль что так никто и не ответил за 5 лет человеку.
Аббревиатура app стандартно означает весь путь до папки приложения, поэтому вместо app принято подставлять например /var/www/html и в этом случае указание файла конфигурации вполне себе уместно. Единственно что для обозначения что это аббревиатура чаще всего пишут @app