Версия фреймворка: 6.x 5.4 4.2

Основы работы с базами данных

Введение

Laravel делает взаимодействие с базами данных чрезвычайно простым в различных бэкэндах баз данных - будь то сырой SQL, построитель запросов или Eloquent ORM. На данный момент Laravel поддерживает четыре системы баз данных:

Настройка

Настройка базы данных для вашего приложения хранится в config/database.php. Здесь вы можете указать все используемые вами соединения к БД, а также задать соединение по умолчанию. Примеры настройки большинства поддерживаемых систем БД находятся в этом же файле.

По умолчанию настройка среды Laravel уже готова к использованию с Laravel Homestead — удобной виртуальной машиной для Laravel-разработки на вашей локальной машине. Разумеется, вы можете изменить эти настройки для работы с вашей локальной БД.

Настройка SQLite

После создания новой базы данных SQLite при помощи команды touch database/database.sqlite, вы можете настроить переменные вашей среды для этой новой базы данных, используя её абсолютный путь:

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

To enable foreign key constraints for SQLite connections, you should set the DB_FOREIGN_KEYS environment variable to true:

DB_FOREIGN_KEYS=true

Настройка с использованием URL

Обычно соединения с базами данных настраиваются с использованием нескольких значений конфигурации, таких как host, database, username, password и др. Каждое из этих значений конфигурации имеет свою собственную соответствующую переменную окружения. Это означает, что при конфигурировании информации о подключении к базе данных на производственном сервере, необходимо управлять несколькими переменными окружения.

Некоторые облачные провайдеры баз данных, такие как Heroku, предоставляют единый URL базы данных, который содержит всю информацию о подключении к базе данных в одной строке. Пример URL базы данных может выглядеть следующим образом:

mysql://root:password@127.0.0.1/forge?charset=UTF-8

Эти URL обычно следуют стандартной схеме:

driver://username:password@host:port/database?options

Для удобства Laravel поддерживает эти URL-адреса в качестве альтернативной настройке вашей базы данных с несколькими вариантами конфигурации. Если присутствует конфигурационная опция url (или соответствующая переменная окружения DATABASE_URL), то она будет использоваться для извлечения информации о подключении к БД и учетных данных.

Настройка SQL Server

Laravel изначально поддерживает работу с SQL Server; однако, потребуется добавить настройку подключения к БД в конфиге config/database.php:

'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. это делается очень просто, и всегда будет использоваться соответствующее соединение, неважно используете ли вы сырые sql-запросы, построитель запросов Laravel или Eloquent ORM.

Чтобы увидеть, как должны быть настроены соединения чтения/записи, давайте взглянем на этот пример:

'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.1',
            '196.168.1.2',
        ],
    ],
    'write' => [
        'host' => [
            '196.168.1.3',
         ],
    ],
    'sticky'    => true,
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

Обратите внимание, что в массив настроек были добавлены три элемента: read, write и sticky. Первые два элемента представляют собой массив с одним элементом: host. Остальные параметры БД для подключений чтения/записи будут заимствованы из основного массива mysql.

Вам стоит размещать элементы в массивах read и write aтолько если вы хотите переопределить их значения из основного массива. Таким образом, в этом случае, 192.168.1.1 будет использоваться как хост для подключения "чтения", а 192.168.1.2 - для подключения "записи". Учётные данные для БД, префикс, набор символов, и все другие параметры основного массива mysql будут использованы для обоих подключений.

Размещать элементы в массивах read и write нужно только в том случае, если вы хотите переопределить значения из главного массива. Таким образом, в этом случае, 192.168.1.1 будет использоваться в качестве хоста для соединения для чтения, а 192.168.1.3 - для соединения для записи. Остальные опции будут совместно использоваться для обоих соединений.

Опция sticky

Опция sticky является опциональным значением. Если опция sticky включена и в течение текущего цикла работы с БД была выполнена операция "запись", то при любых дальнейших операциях "чтения" будет использоваться соединение "запись". Это гарантирует, что любые данные, записанные во время цикла запроса, могут быть немедленно считаны из БД во время того же самого запроса. Вы сами решаете, является ли это желаемым поведением вашего приложения.

Использование нескольких соединений с БД

При использовании нескольких соединений с БД вы можете получить доступ к каждому из них через метод connection фасада DB. Передаваемое в этот метод имя name должно соответствовать одному из перечисленных в файле config/database.php:

$users = DB::connection('foo')->select(...);

Вы также можете получить низкоуровневый объект PDO для этого подключения методом getPdo на экземпляре подключения:

$pdo = DB::connection()->getPdo();

Выполнение сырых SQL-запросов

После того как вы настроили соединение с базой данных, вы можете выполнять запросы, используя фасад DB. Этот фасад имеет методы для каждого типа запроса: select, update, insert, delete и statement.

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

Чтобы выполнить базовый запрос, можно использовать метод select фасада DB:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    /**
     * Показать список всех пользователей приложения.
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::select('select * from users where active = ?', [1]);

        return view('user.index', ['users' => $users]);
    }
}

Первый аргумент метода 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-запрос первым аргументом, а вторым — привязкиt:

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

Выполнение запроса 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');

Прослушивание событий запросов

Если вы хотите получать каждый выполненный вашим приложением SQL-запрос, используйте метод listen. Этот метод полезен для логгирования запросов и отладки. Вы можете зарегистрировать свой слушатель запросов в сервис-провайдере:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Регистрация сервис-провайдера.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Загрузка всех сервисов приложения.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }
}

Транзакции БД

Для выполнения набора запросов внутри одной транзакции вы можете использовать метод transaction фасада DB. Если в функции-замыкании произойдёт исключение, транзакция автоматически откатится. А если функция выполнится успешно, транзакция автоматически применится к БД:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
});

Обработка взаимных блокировок

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

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
}, 5);

Ручное использование транзакций

Если вы хотите запустить транзакцию вручную и иметь полный контроль над её откатом и применением, используйте метод beginTransaction фасада DB:

DB::beginTransaction();

Вы можете откатить транзакцию методом rollBack:

DB::rollBack();

Наконец, вы можете применить транзакцию методом commit:

DB::commit();
Методы фасада DB для транзакций контролируют и транзакции в построителя запросов и в Eloquent ORM.