Методы транзакции фасада
DB
контролируют как конструктор запросов,
так и Eloquent ORM.
Содержание:
Laravel делает взаимодействие с базой данных невероятно простым благодаря гибкому конструктору запросов. Такие возможности достигаются используя Eloquent ORM, который позволяет работать с различными базами данных, такими как:
Конфигурация базы данных для вашего приложения располагается в config/database.php
.
В этом файле вы можете определить все соединения с базой данных, а ещё указать какое соединения
неоходимо использовать по умолчанию. Примеры для большинства поддерживаемый баз данных
находятся в этом файле.
По умолчанию, конфигурация окружения готова к использованию с Laravel Homestead, которое является удобной виртуальной машиной для локальной разработки на Ларавел. Вы можете свободно изменить конфигурацию так, как это необходимо для вашей локальной базы данных.
После создания базы данных SQLite используя команду такую как touch database/database.sqlite
,
вы можете легко настроить переменные среды к точке созданной базы данных путём использования
абсолютного пути бд:
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite
Чтобы включить ограничения внешнего ключа для соединения SQLite, вам необходимо добавить
опцию foreign_key_constraints
в ваш файл конфигурации config/database.php
:
'sqlite' => [
// ...
'foreign_key_constraints' => true,
],
Обыкновенно, соединия базы данных настраиваются с использованием нескольких значений конфигураций,
таких как host
, database
, username
, password
и другие.
Каждое из этих значений имеет соотвествующие значения среды. Это означает, что при настройке соединения
вашей базы данных на сервере, вам необходимо несколькими переменными среды.
Некоторые провайдеры бд, такие как Heroku, предоставляют единый "URL" для бд, который содержит всю информацию для базы данных в простой строке. Пример URL базы данных может выглядеть таким образом:
driver://username:password@host:port/database?options
Эти URLs обычно придерживаются типовой схемы:
driver://username:password@host:port/database?options
Для удобства, Laravel поддерживает эти URL как альтернативу для настройки вашей базы
данных с несколькими опциями конфигурации. Если url
или соотвествующая
переменная среды DATABASE_URL
присутствует, она будет использована для
того, чтобы извлечь информацию о соединении базы данных и другие данные.
Иногда вы можете использовать одно соединение базы данных для выражений с SELECT и другое для INSERT, UPDATE, и DELETE. Ларавел позволяет реализовать задуманное легко, нужное соединение будет всегда использовано вне зависимости от того, что вы используете: запросы, конструктор запросов или 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' => '',
],
Надо отметить, что 3 ключа были добавлены в массив конфигурации: read
, write
и
sticky
. Ключи read
и write
имеют массив значений,
содержащий одиночный ключ host
. Остальные опции базы данных для соединений
read
и write
будут добавлены из основного массива mysql
.
Вам лишь необходимо разместить элеменыт вы массивах read
и write
, если вы
хотите переписать значения из основного массива. Поэтому, в этом случае, 192.168.1.1
будет использовано в качестве хоста для соединения read
, в то время как
192.168.1.3
будет использовано для соединения write
.
Учётные данные базы данных, префикс, набор символов и другие опции
в основном массиве mysql
будут доступны для обоих соединений.
sticky
Опция sticky
это значение optional, которое может быть использовано
для того, чтобы разрешить мгновенное чтение записей, которые были записаны в течение текущего
цикла запроса. Если опция sticky
включена и операция write
была выполнена
для бд в течение текущего цикла, любые последующие операции read
будут использовать
соединение write
. Это является гарантией того, что данные записанные во время запроса
могут быть прочитаны из бд во время того же запроса. Вам решать, стоит ли включать такую логику
для вашего приложения.
При использовании нескольких соединений, вы можете получить доступ к соединению через метод
connection
для фасада DB
. В метод connection
передаётся
name
, которое должно соотвествовать одному из соединений, перечисленных в вашем
файле конфигурации config/database.php
:
$users = DB::connection('foo')->select(...);
Вы также можете получить доступ к необработанному базовому экземпляру используя метод
getPdo
для экземпляра соединения:
$pdo = DB::connection()->getPdo();
После настройки соединения с вашей базой данных, вы можете запустить запросы используя
фасад DB
. Фасад DB
предоставляет методы для каждого типа запросов:
select
, update
, insert
, delete
,
и statement
.
Чтобы запустить базовый запрос, вы можете использовать метод select
для фасада
DB
:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
/**
* Show a list of all of the application's users.
*
* @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
всегда будет возвращать массив array
результатов.
Каждый результат внутри массива будет stdClass
объектом PHP, что позволяет
вам получить конкретное значениеs:
foreach ($users as $user) {
echo $user->name;
}
Вместо использования ?
для связывания ваших параметров, вы можете выполнить
запрос используя именное связывание:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
Чтобы выполнить выражение с insert
, вы можете использовать метод insert
для фасада DB
. Как и для select
, этот метод берёт выражение SQL
в качестве первого аргумента и связывание в качестве второго:
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
Метод update
должен быть использован для обновления существующих записей в базе данных.
В качестве ответа должно вернуться число строк, которые были подвергнуты влиянию:
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
Метод delete
нужно использовать для удаления записей из базы данных.
Как и в случае с update
, вернётся число затронутых строк:
$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
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
}
Вы можете использовать метод transaction
для фасада DB
для запуска
набора операций внутри транзакции бд. Если появилось исключение внутри замыкания транзакции,
то будет автоматически откат в исходную позицию. Если Closure
выполняется успешно,
транзация будет автоматически зафиксирована. Вам не нужно беспокоиться об откатах в исходную
позицию или комитах при использовании метода transaction
:
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();