Skip to content

6. База данных: Миграции

1. Введение

Миграции похожи на систему контроля версий для вашей базы данных, позволяя вашей команде определять и совместно использовать схему базы данных приложения. Если вам когда-либо приходилось просить коллегу вручную добавить столбец в локальную схему базы данных после получения ваших изменений из системы контроля версий, вы сталкивались с проблемой, которую решают миграции базы данных.

Фасад Laravel Schema предоставляет независимую от типа базы данных поддержку для создания и изменения таблиц во всех поддерживаемых Laravel системах баз данных. Как правило, миграции используют этот фасад для создания и изменения таблиц и столбцов базы данных.

2. Создание миграций

Вы можете использовать Artisan-команду make:migration, чтобы создать миграцию базы данных. Новая миграция будет помещена в ваш каталог database/migrations. Имя каждого файла миграции содержит временную метку, которая позволяет Laravel определить порядок миграций:

php artisan make:migration create_flights_table

Laravel использует имя миграции, чтобы попытаться угадать имя таблицы и определить, будет ли миграция создавать новую таблицу. Если Laravel удастся определить имя таблицы из имени миграции, он предварительно заполнит сгенерированный файл миграции указанной таблицей. В противном случае вы можете просто указать таблицу в файле миграции вручную.

Если вы хотите указать пользовательский путь для создаваемой миграции, вы можете использовать опцию --path при выполнении команды make:migration. Указанный путь должен быть относительно базового пути вашего приложения.

lightbulb

Шаблоны миграций могут быть изменены с помощью публикации шаблонов.

2.1. Сжатие миграций

По мере разработки вашего приложения со временем у вас может накопиться все больше миграций. Это может привести к тому, что каталог database/migrations будет перегружен сотнями миграций. При необходимости вы можете "сжать" ваши миграции в один SQL-файл. Чтобы начать, выполните команду schema:dump:

php artisan schema:dump
 
# Dump the current database schema and prune all existing migrations...
php artisan schema:dump --prune

Когда вы выполните эту команду, Laravel создаст файл "схемы" в каталоге database/schema вашего приложения. Имя файла схемы будет соответствовать подключению к базе данных. Теперь, если вы попытаетесь выполнить миграцию базы данных и другие миграции еще не были выполнены, Laravel сначала выполнит SQL-выражения из файла схемы для используемого вами подключения к базе данных. После выполнения SQL-выражений из файла схемы Laravel выполнит все оставшиеся миграции, которые не были включены в дамп схемы.

Если тесты вашего приложения используют другое подключение к базе данных, отличное от того, которое вы обычно используете при локальной разработке, убедитесь, что вы создали файл схемы для этого подключения к базе данных, чтобы ваши тесты могли создать базу данных. Вы можете сделать это после создания дампа подключения к базе данных, которое вы обычно используете при локальной разработке:

php artisan schema:dump
php artisan schema:dump --database=testing --prune

Вам следует сохранить файл схемы базы данных в системе контроля версий, чтобы другие новые разработчики в вашей команде могли быстро создать начальную структуру базы данных вашего приложения.

exclamation

Сжатие миграций доступно только для баз данных MariaDB, MySQL, PostgreSQL и SQLite и использует клиент командной строки базы данных.

3. Структура миграции

Класс миграции содержит два метода: up и down. Метод up используется для добавления новых таблиц, столбцов или индексов в вашу базу данных, а метод down должен отменять операции, выполненные методом up.

В обоих этих методах вы можете использовать конструктор схем Laravel для удобного создания и изменения таблиц. Чтобы узнать обо всех доступных методах конструктора Schema, ознакомьтесь с его документацией. Например, следующая миграция создает таблицу flights:

<?php
 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
 
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::drop('flights');
}
};

3.1. Установка подключения для миграции

Если ваша миграция будет работать с подключением к базе данных, отличным от подключения по умолчанию в вашем приложении, вам следует установить свойство $connection в вашей миграции:

/**
* The database connection that should be used by the migration.
*
* @var string
*/
protected $connection = 'pgsql';
 
/**
* Run the migrations.
*/
public function up(): void
{
// ...
}

4. Выполнение миграций

Чтобы выполнить все непримененные миграции, выполните Artisan-команду migrate:

php artisan migrate

Если вы хотите увидеть, какие миграции были выполнены до текущего момента, вы можете использовать Artisan-команду migrate:status:

php artisan migrate:status

Если вы хотите увидеть SQL-запросы, которые будут выполнены миграциями, но не запускать их, вы можете добавить флаг --pretend к команде migrate:

php artisan migrate --pretend

4.0.1. Изоляция выполнения миграций

Если вы разворачиваете свое приложение на нескольких серверах и выполняете миграции в рамках процесса развертывания, вы, вероятно, не хотите, чтобы два сервера одновременно пытались мигрировать базу данных. Чтобы этого избежать, вы можете использовать опцию isolated при вызове команды migrate.

Когда используется опция isolated, Laravel создаст атомарную блокировку с помощью драйвера кэша вашего приложения перед попыткой выполнить миграции. Все другие попытки выполнить команду migrate, пока эта блокировка активна, не будут выполнены; однако команда завершится с успешным кодом завершения:

php artisan migrate --isolated
exclamation

Чтобы использовать эту функцию, ваше приложение должно использовать драйвер кэша memcached, redis, dynamodb, database, file или array в качестве драйвера кэша по умолчанию. Кроме того, все серверы должны быть подключены к одному центральному серверу кэша.

4.0.2 Принудительное выполнение миграций в рабочей среде

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

php artisan migrate --force

4.1. Откат миграций

Чтобы откатить последнюю операцию миграции, вы можете использовать Artisan-команду rollback. Эта команда откатывает последний "пакет" миграций, который может включать несколько файлов миграций:

php artisan migrate:rollback

Вы можете откатить ограниченное количество миграций, указав опцию step в команде rollback. Например, следующая команда откатит последние пять миграций:

php artisan migrate:rollback --step=5

Вы можете откатить определенный "пакет" миграций, указав опцию batch в команде rollback, где опция batch соответствует значению пакета в таблице migrations вашей базы данных. Например, следующая команда откатит все миграции в третьем пакете:

php artisan migrate:rollback --batch=3

Если вы хотите увидеть SQL-запросы, которые будут выполнены миграциями, но не запускать их, вы можете добавить флаг --pretend к команде migrate:rollback:

php artisan migrate:rollback --pretend

Команда migrate:reset откатит все миграции вашего приложения:

php artisan migrate:reset

4.1. Откат и повторное выполнение миграций одной командой

Команда migrate:refresh откатит все ваши миграции, а затем выполнит команду migrate. Эта команда фактически заново создаёт всю вашу базу данных:

php artisan migrate:refresh
 
# Refresh the database and run all database seeds...
php artisan migrate:refresh --seed

Вы можете откатить и повторно выполнить ограниченное количество миграций, указав опцию step в команде refresh. Например, следующая команда откатит и повторно выполнит последние пять миграций:

php artisan migrate:refresh --step=5

4.2. Удаление всех таблиц и выполнение миграций

Команда migrate:fresh удалит все таблицы из базы данных, а затем выполнит команду migrate:

php artisan migrate:fresh
 
php artisan migrate:fresh --seed

По умолчанию команда migrate:fresh удаляет таблицы только из подключения к базе данных по умолчанию. Однако вы можете использовать опцию --database, чтобы указать подключение к базе данных, для которого должны быть выполнены миграции. Имя подключения к базе данных должно соответствовать подключению, определенному в конфигурационном файле вашего приложения:

php artisan migrate:fresh --database=admin
exclamation

Команда migrate:fresh удалит все таблицы базы данных независимо от их префикса. Эту команду следует использовать с осторожностью, если вы работаете с базой данных, которая используется другими приложениями.

5. Таблицы

5.1. Создание таблиц

Чтобы создать новую таблицу базы данных, используйте метод create фасада Schema. Метод create принимает два аргумента: первый — это имя таблицы, а второй — замыкание, которое получает объект Blueprint, используемый для определения новой таблицы:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->timestamps();
});

7. Индексы

7.1. Создание индексов

Конструктор схем Laravel поддерживает несколько типов индексов. В следующем примере создается новый столбец email и указывается, что его значения должны быть уникальными. Чтобы создать индекс, мы можем использовать метод unique, добавленный к определению столбца:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('users', function (Blueprint $table) {
$table->string('email')->unique();
});