Подписывайтесь на наш Telegram канал и будьте в курсе всех событий.
Ищете работу? Мы поможем!
Ищете работу? Мы поможем!

База данных · Миграции

Введение

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

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

Генерация миграций

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

php artisan make:migration create_flights_table

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

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

Заготовки (stubs) миграции можно настроить с помощью публикации заготовок.

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

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

php artisan schema:dump

# Выгрузить текущую схему БД и удалить все существующие миграции ...
php artisan schema:dump --prune

В результате выполнения этой команды Laravel запишет дамп базы данных в каталог database/schema вашего приложения. Теперь, при запуске миграции базы данных, Laravel сначала выполнит SQL-операторы дампа (если никакие другие миграции не выполнялись). Затем Laravel выполнит все оставшиеся миграции, которые не были включены в дамп схемы БД.

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

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

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

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

Структура миграций

Класс миграции содержит два метода: 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
{
    /**
     * Запустить миграцию.
     */
    public function up(): void
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    /**
     * Обратить миграции.
     */
    public function down(): void
    {
        Schema::drop('flights');
    }
}

Указание соединения миграции

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

/**
 * Соединение с БД, которое должно использоваться миграцией.
 *
 * @var string
 */
protected $connection = 'pgsql';

/**
 * Запустить миграцию.
 */
public function up(): void
{
    // ...
}

Запуск миграций

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

php artisan migrate

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

php artisan migrate:status

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

php artisan migrate --pretend

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

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

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

php artisan migrate --isolated

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

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

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

php artisan migrate --force

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

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

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

Откат и миграция с помощью одной команды

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

php artisan migrate:refresh

// Обновляем базу данных и запускаем все наполнители базы данных ...
php artisan migrate:refresh --seed

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

php artisan migrate:refresh --step=5

Удаление всех таблиц с последующей миграцией

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

php artisan migrate:fresh

php artisan migrate:fresh --seed

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

php artisan migrate:fresh --database=admin

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

Таблицы

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

Чтобы создать новую таблицу базы данных, используйте метод 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();
});

При создании таблицы вы можете использовать любой из методов столбцов построителя схемы для определения столбцов таблицы.

Определение наличия таблицы / столбца

Вы можете определить наличие таблицы или столбца с помощью методов hasTable и hasColumn, соответственно:

if (Schema::hasTable('users')) {
    // Таблица `users` существует ...
}

if (Schema::hasColumn('users', 'email')) {
    // Таблица `users` существует и содержит столбец `email` ...
}

Соединение с базой данных и параметры таблицы

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

Schema::connection('sqlite')->create('users', function (Blueprint $table) {
    $table->id();
});

Кроме того, некоторые другие свойства и методы могут использоваться для определения других аспектов создания таблицы. Свойство engine используется для указания механизма хранения таблицы при использовании MySQL:

Schema::create('users', function (Blueprint $table) {
    $table->engine = 'InnoDB';

    // ...
});

Свойства charset и collation могут использоваться для указания набора символов и сопоставления для создаваемой таблицы при использовании MySQL:

Schema::create('users', function (Blueprint $table) {
    $table->charset = 'utf8mb4';
    $table->collation = 'utf8mb4_unicode_ci';

    // ...
});

Метод temporary используется, чтобы указать, что таблица должна быть «временной». Временные таблицы видны только текущему сеансу соединения базы данных и автоматически удаляются при закрытии соединения:

Schema::create('calculations', function (Blueprint $table) {
    $table->temporary();

    // ...
});

Если вы хотите добавить “комментарий” к таблице базы данных, вы можете вызвать метод comment на экземпляре таблицы. Комментарии к таблицам поддерживаются только в MySQL и Postgres:

Schema::create('calculations', function (Blueprint $table) {
    $table->comment('Business calculations');

    // ...
});

Этот код позволит вам добавить комментарий “Business calculations” к таблице “calculations” в вашей базе данных. Это может быть полезно для документации и описания цели таблицы.

Обновление таблиц

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

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

Переименование / удаление таблиц

Чтобы переименовать существующую таблицу базы данных, используйте метод rename:

use Illuminate\Support\Facades\Schema;

Schema::rename($from, $to);

Чтобы удалить существующую таблицу, вы можете использовать методы drop или dropIfExists:

Schema::drop('users');

Schema::dropIfExists('users');

Переименование таблиц с внешними ключами

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

Столбцы

Создание столбцов

Метод table фасада Schema используется для обновления существующих таблиц. Как и метод create, метод table принимает два аргумента: имя таблицы и замыкание, которое получает экземпляр Illuminate\Database\Schema\Blueprint, используемый для добавления столбцов в таблицу:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

Доступные типы столбцов

Построитель схем Blueprint предлагает множество методов, соответствующих различным типам столбцов, которые вы можете добавить в таблицы базы данных. Все доступные методы перечислены в таблице ниже:

bigIncrements()

Метод bigIncrements создает эквивалент автоинкрементного столбца UNSIGNED BIGINT (первичный ключ):

$table->bigIncrements('id');

bigInteger()

Метод bigInteger создает эквивалент столбца BIGINT:

$table->bigInteger('votes');

binary()

Метод binary создает эквивалент столбца BLOB:

$table->binary('photo');

boolean()

Метод boolean создает эквивалент столбца BOOLEAN:

$table->boolean('confirmed');

char()

Метод char создает эквивалент столбца CHAR указанной длины:

$table->char('name', 100);

dateTimeTz()

Метод dateTimeTz создает эквивалент столбца DATETIME (с часовым поясом) с необязательной точностью (общее количество цифр):

$table->dateTimeTz('created_at', $precision = 0);

dateTime()

Метод dateTime создает эквивалент столбца DATETIME с необязательной точностью (общее количество цифр):

$table->dateTime('created_at', $precision = 0);

date()

Метод date создает эквивалент столбца DATE:

$table->date('created_at');

decimal()

Метод decimal создает эквивалент столбца DECIMAL с точностью (общее количество цифр) и масштабом (десятичные цифры):

$table->decimal('amount', $precision = 8, $scale = 2);

double()

Метод double создает эквивалент столбца DOUBLE с точностью (общее количество цифр) и масштабом (десятичные цифры):

$table->double('amount', 8, 2);

enum()

Метод enum создает эквивалент столбца ENUM с указанием допустимых значений:

$table->enum('difficulty', ['easy', 'hard']);

float()

Метод float создает эквивалент столбца FLOAT с точностью (общее количество цифр) и масштабом (десятичные цифры):

$table->float('amount', 8, 2);

foreignId()

Метод foreignId создает эквивалент столбца UNSIGNED BIGINT:

$table->foreignId('user_id');

foreignIdFor()

Метод foreignIdFor добавляет столбец с именем {column}_id, эквивалентный для заданного класса модели. Тип столбца будет UNSIGNED BIGINT, CHAR(36) или CHAR(26), в зависимости от типа ключа модели:

$table->foreignIdFor(User::class);

foreignUlid()

Метод foreignUlid создает столбец, эквивалентный ULID:

$table->foreignUlid('user_id');

foreignUuid()

Метод foreignUuid создает эквивалент столбца UUID:

$table->foreignUuid('user_id');

geometryCollection()

Метод geometryCollection создает эквивалент столбца GEOMETRYCOLLECTION:

$table->geometryCollection('positions');

geometry()

Метод geometry создает эквивалент столбца GEOMETRY:

$table->geometry('positions');

id()

Метод id является псевдонимом метода bigIncrements. По умолчанию метод создает столбец id; однако, вы можете передать имя столбца, если хотите присвоить столбцу другое имя:

$table->id();

increments()

Метод increments создает эквивалент автоинкрементного столбца UNSIGNED INTEGER в качестве первичного ключа:

$table->increments('id');

integer()

Метод integer создает эквивалент столбца INTEGER:

$table->integer('votes');

ipAddress()

Метод ipAddress создает эквивалент столбца VARCHAR:

$table->ipAddress('visitor');

При использовании Postgres будет создан столбец INET.

json()

Метод json создает эквивалент столбца JSON:

$table->json('options');

jsonb()

Метод jsonb создает эквивалент столбца JSONB:

$table->jsonb('options');

lineString()

Метод lineString создает эквивалент столбца LINESTRING:

$table->lineString('positions');

longText()

Метод longText создает эквивалент столбца LONGTEXT:

$table->longText('description');

macAddress()

Метод macAddress создает столбец, предназначенный для хранения MAC-адреса. Некоторые системы баз данных, такие как PostgreSQL, имеют специальный тип столбца для этого типа данных. Другие системы баз данных будут использовать столбец строкового эквивалента:

$table->macAddress('device');

mediumIncrements()

Метод mediumIncrements создает эквивалент автоинкрементного столбца UNSIGNED MEDIUMINT в качестве первичного ключа:

$table->mediumIncrements('id');

mediumInteger()

Метод mediumInteger создает эквивалент столбца MEDIUMINT:

$table->mediumInteger('votes');

mediumText()

Метод mediumText создает эквивалент столбца MEDIUMTEXT:

$table->mediumText('description');

morphs()

Метод morphs – это удобный метод, который добавляет эквивалент столбца {column}_id и столбца {column}_type с типом данных VARCHAR. Тип данных столбца {column}_id будет UNSIGNED BIGINT, CHAR(36) или CHAR(26), в зависимости от типа ключа модели.

Этот метод предназначен для использования при определении столбцов, необходимых для полиморфного отношения Eloquent. В следующем примере будут созданы столбцы taggable_id и taggable_type:

$table->morphs('taggable');

multiLineString()

Метод multiLineString создает эквивалент столбца MULTILINESTRING:

$table->multiLineString('positions');

multiPoint()

Метод multiPoint создает эквивалент столбца MULTIPOINT:

$table->multiPoint('positions');

multiPolygon()

Метод multiPolygon создает эквивалент столбца MULTIPOLYGON:

$table->multiPolygon('positions');

nullableTimestamps()

Метод nullableTimestamps является псевдонимом метода timestamps:

$table->nullableTimestamps(0);

nullableMorphs()

Метод аналогичен методу morphs; тем не менее, создаваемый столбец будет иметь значение NULL:

$table->nullableMorphs('taggable');

nullableUlidMorphs()

Этот метод аналогичен методу ulidMorphs; однако создаваемые столбцы будут “nullable” (допускающими значение null):

$table->nullableUlidMorphs('taggable');

nullableUuidMorphs()

Метод аналогичен методу uuidMorphs; тем не менее, создаваемый столбец будет иметь значение NULL:

$table->nullableUuidMorphs('taggable');

point()

Метод point создает эквивалент столбца POINT:

$table->point('position');

polygon()

Метод polygon создает эквивалент столбца POLYGON:

$table->polygon('position');

rememberToken()

Метод rememberToken создает NULL-эквивалент столбца VARCHAR(100), предназначенный для хранения текущего токена аутентификации:

$table->rememberToken();

set()

Метод set создает эквивалент столбца SET с заданным списком допустимых значений:

$table->set('flavors', ['strawberry', 'vanilla']);

smallIncrements()

Метод smallIncrements создает эквивалент автоинкрементного столбца UNSIGNED SMALLINT в качестве первичного ключа:

$table->smallIncrements('id');

smallInteger()

Метод smallInteger создает эквивалент столбца SMALLINT:

$table->smallInteger('votes');

softDeletesTz()

Метод softDeletesTz добавляет NULL-эквивалент столбца TIMESTAMP (с часовым поясом) с необязательной точностью (общее количество цифр). Этот столбец предназначен для хранения временной метки deleted_at, необходимой для функции «программного удаления» Eloquent:

$table->softDeletesTz($column = 'deleted_at', $precision = 0);

softDeletes()

Метод softDeletes добавляет NULL-эквивалент столбца TIMESTAMP с необязательной точностью (общее количество цифр). Этот столбец предназначен для хранения временной метки deleted_at, необходимой для функции «программного удаления» Eloquent:

$table->softDeletes($column = 'deleted_at', $precision = 0);

string()

Метод string создает эквивалент столбца VARCHAR указанной длины:

$table->string('name', 100);

text()

Метод text создает эквивалент столбца TEXT:

$table->text('description');

timeTz()

Метод timeTz создает эквивалент столбца TIME (с часовым поясом) с необязательной точностью (общее количество цифр):

$table->timeTz('sunrise', $precision = 0);

time()

Метод time создает эквивалент столбца TIME с необязательной точностью (общее количество цифр):

$table->time('sunrise', $precision = 0);

timestampTz()

Метод timestampTz создает эквивалент столбца TIMESTAMP (с часовым поясом) с необязательной точностью (общее количество цифр):

$table->timestampTz('added_at', $precision = 0);

timestamp()

Метод timestamp создает эквивалент столбца TIMESTAMP с необязательной точностью (общее количество цифр):

$table->timestamp('added_at', $precision = 0);

timestampsTz()

Метод timestampsTz создает столбцы created_at и updated_at, эквивалентные TIMESTAMP (с часовым поясом) с необязательной точностью (общее количество цифр):

$table->timestampsTz($precision = 0);

timestamps()

Метод timestamps method creates created_at and updated_at TIMESTAMP с необязательной точностью (общее количество цифр):

$table->timestamps($precision = 0);

tinyIncrements()

Метод tinyIncrements создает эквивалент автоинкрементного столбца UNSIGNED TINYINT в качестве первичного ключа:

$table->tinyIncrements('id');

tinyInteger()

Метод tinyInteger создает эквивалент столбца TINYINT:

$table->tinyInteger('votes');

tinyText()

Метод tinyText создаёт эквивалент столбца TINYTEXT:

$table->tinyText('notes');    

unsignedBigInteger()

Метод unsignedBigInteger создает эквивалент столбца UNSIGNED BIGINT:

$table->unsignedBigInteger('votes');

unsignedDecimal()

Метод unsignedDecimal создает эквивалент столбца UNSIGNED DECIMAL с необязательной точностью (общее количество цифр) и масштабом (десятичные цифры):

$table->unsignedDecimal('amount', $precision = 8, $scale = 2);

unsignedInteger()

Метод unsignedInteger создает эквивалент столбца UNSIGNED INTEGER:

$table->unsignedInteger('votes');

unsignedMediumInteger()

Метод unsignedMediumInteger создает эквивалент столбца UNSIGNED MEDIUMINT:

$table->unsignedMediumInteger('votes');

unsignedSmallInteger()

Метод unsignedSmallInteger создает эквивалент столбца UNSIGNED SMALLINT:

$table->unsignedSmallInteger('votes');

unsignedTinyInteger()

Метод unsignedTinyInteger создает эквивалент столбца UNSIGNED TINYINT:

$table->unsignedTinyInteger('votes');

Метод ulidMorphs()

Метод ulidMorphs – это удобный метод, который добавляет эквивалент столбца {column}_id типа CHAR(26) и столбца {column}_type типа VARCHAR.

Этот метод предназначен для использования при определении столбцов, необходимых для полиморфных Eloquent отношений, которые используют ULID идентификаторы. В следующем примере будут созданы столбцы taggable_id и taggable_type:

$table->ulidMorphs('taggable');

uuidMorphs()

Метод uuidMorphs – это удобный метод, который добавляет эквивалент столбца CHAR(36) ({column}_id) и эквивалент столбца VARCHAR ({column}_type).

Этот метод предназначен для использования при определении столбцов, необходимых для полиморфного отношения Eloquent, использующего идентификаторы UUID. В следующем примере будут созданы столбцы taggable_id и taggable_type:

$table->uuidMorphs('taggable');

Метод ulid()

Метод ulid создает столбец, эквивалентный ULID:

$table->ulid('id');

Метод ulid создает столбец, эквивалентный ULID и присваивает ему имя 'id’.

uuid()

Метод uuid создает эквивалент столбца UUID:

$table->uuid('id');

year()

Метод year создает эквивалент столбца YEAR:

$table->year('birth_year');

Модификаторы столбца

В дополнение к типам столбцов, перечисленным выше, есть несколько «модификаторов» столбцов, которые вы можете использовать при добавлении столбца в таблицу базы данных. Например, чтобы сделать столбец «допускающим значение NULL», вы можете использовать метод nullable:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->nullable();
});

В следующей таблице представлены все доступные модификаторы столбцов. В этот список не входят модификаторы индексов:

Модификатор Описание
->after('column') Поместить столбец «после» другого столбца (MySQL).
->autoIncrement() Установить столбцы INTEGER как автоинкрементные (первичный ключ).
->charset('utf8mb4') Указать набор символов для столбца (MySQL).
->collation('utf8mb4_unicode_ci') Указать параметры сравнения для столбца (MySQL/PostgreSQL/SQL Server).
->comment('my comment') Добавить комментарий к столбцу (MySQL/PostgreSQL).
->default($value) Указать значение «по умолчанию» для столбца.
->first() Поместить столбец «первым» в таблице (MySQL).
->from($integer) Установить начальное значение автоинкрементного поля (MySQL / PostgreSQL).
->invisible() Сделать столбец "невидимым" для запросов SELECT * (MySQL).
->nullable($value = true) Позволить (по умолчанию) значения NULL для вставки в столбец.
->storedAs($expression) Создать сохраненный генерируемый столбец (MySQL / PostgreSQL).
->unsigned() Установить столбцы INTEGER как UNSIGNED (MySQL).
->useCurrent() Установить столбцы TIMESTAMP для использования CURRENT_TIMESTAMP в качестве значения по умолчанию.
->useCurrentOnUpdate() Установить столбцы TIMESTAMP для использования CURRENT_TIMESTAMP при обновлении записи (MySQL).
->virtualAs($expression) Создать виртуальный генерируемый столбец (MySQL / PostgreSQL / SQLite).
->generatedAs($expression) Создать столбец идентификаторов с указанными параметрами последовательности (PostgreSQL).
->always() Определить приоритет значений последовательности над вводом для столбца идентификаторов (PostgreSQL).
->isGeometry() Установить для пространственного столбца тип geometry - по умолчанию устанавливается geography (PostgreSQL).

Выражения для значений по умолчанию

Модификатор default принимает значение или экземпляр Illuminate\Database\Query\Expression. Использование экземпляра Expression не позволит Laravel заключить значение в кавычки и позволит вам использовать функции, специфичные для базы данных. Одна из ситуаций, когда это особенно полезно, когда вам нужно назначить значения по умолчанию для столбцов JSON:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Migrations\Migration;

return new class extends Migration
{
    /**
     * Запустить миграцию.
     */
    public function up(): void
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->json('movies')->default(new Expression('(JSON_ARRAY())'));
            $table->timestamps();
        });
    }
}

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

Порядок столбцов

Метод after добавляет набор столбцов после указанного существующего столбца в схеме базы данных MySQL:

$table->after('password', function (Blueprint $table) {
    $table->string('address_line1');
    $table->string('address_line2');
    $table->string('city');
});

Изменение столбцов

Метод change позволяет вам изменять тип и атрибуты существующих колонок. Например, вы можете захотеть увеличить размер колонки типа string. Чтобы увидеть метод change в действии, давайте увеличим размер колонки name с 25 до 50. Для этого мы просто определяем новое состояние колонки и затем вызываем метод change:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change();
});

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

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')->unsigned()->default(1)->comment('мой комментарий')->change();
});

Изменение колонок в SQLite

Перед изменением столбца вы должны установить пакет doctrine/dbal с помощью менеджера пакетов Composer. Библиотека Doctrine DBAL используется для определения текущего состояния столбца и для создания запросов SQL, необходимых для внесения запрошенных изменений в столбец:

composer require doctrine/dbal

Если вы планируете изменять столбцы, созданные с помощью метода timestamp, вы также должны добавить следующую конфигурацию в файл config/database.php вашего приложения:

use Illuminate\Database\DBAL\TimestampType;

'dbal' => [
    'types' => [
        'timestamp' => TimestampType::class,
    ],
],

При использовании пакета doctrine/dbal, можно изменять следующие типы столбцов: bigInteger, binary, boolean, char, date, dateTime, dateTimeTz, decimal, double, integer, json, longText, mediumText, smallInteger, string, text, time, tinyText, unsignedBigInteger, unsignedInteger, unsignedSmallInteger, ulid и uuid.

Переименование столбцов

Для переименования столбца вы можете использовать метод renameColumn, предоставленный строителем схемы:

Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('from', 'to');
});

Переименование столбцов в устаревших базах данных

Если вы используете установку базы данных, выпущенную ранее, чем одна из следующих версий, убедитесь, что вы установили библиотеку doctrine/dbal с помощью менеджера пакетов Composer перед переименованием столбца:

  • MySQL < 8.0.3
  • MariaDB < 10.5.2
  • SQLite < 3.25.0

Удаление столбцов

Для удаления столбца вы можете использовать метод dropColumn в билдере схемы:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('votes');
});

Вы можете удалить несколько столбцов из таблицы, передав массив имен столбцов методу dropColumn:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn(['votes', 'avatar', 'location']);
});

Удаление столбцов в старых базах данных

Если вы используете версию SQLite, предшествующую 3.35.0, вам необходимо установить пакет doctrine/dbal с помощью менеджера пакетов Composer, прежде чем можно будет использовать метод dropColumn. При этом не поддерживается удаление или изменение нескольких столбцов в рамках одной миграции при использовании этого пакета.

Доступные псевдонимы команд

Laravel содержит несколько удобных методов, связанных с удалением общих типов столбцов. Каждый из этих методов описан в таблице ниже:

Команда Описание
$table->dropMorphs('morphable'); Удалить столбцы morphable_id и morphable_type.
$table->dropRememberToken(); Удалить столбец remember_token.
$table->dropSoftDeletes(); Удалить столбец deleted_at.
$table->dropSoftDeletesTz(); Псевдоним dropSoftDeletes().
$table->dropTimestamps(); Удалить столбцы created_at и updated_at.
$table->dropTimestampsTz(); Псевдоним dropTimestamps().

Индексы

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

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

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->unique();
});

В качестве альтернативы вы можете создать индекс после определения столбца. Для этого вы должны вызвать метод unique построителя схемы Blueprint. Этот метод принимает имя столбца, который должен получить уникальный индекс:

$table->unique('email');

Вы даже можете передать массив столбцов методу индекса для создания составного индекса:

$table->index(['account_id', 'created_at']);

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

$table->unique('email', 'unique_email');

Доступные типы индексов

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

Команда Описание
$table->primary('id'); Добавить первичный ключ.
$table->primary(['id', 'parent_id']); Добавить составной ключ.
$table->unique('email'); Добавить уникальный индекс.
$table->index('state'); Добавляет простой индекс.
$table->fulltext('body'); Добавляет полнотекстовый индекс (MySQL/PostgreSQL).
$table->fulltext('body')->language('english'); Добавляет полнотекстовый индекс для указанного языка (PostgreSQL).
$table->spatialIndex('location'); Добавляет пространственный индекс (кроме SQLite).

Длина индекса и MySQL / MariaDB

По умолчанию Laravel использует набор символов utf8mb4. Если вы используете версию MySQL древнее 5.7.7 или MariaDB древнее 10.2.2, то вам может потребоваться вручную настроить длину строки по умолчанию, сгенерированную миграциями, чтобы MySQL мог создавать для них индексы. Вы можете настроить длину строки по умолчанию, вызвав метод Schema::defaultStringLength в методе boot вашего класса App\Providers\AppServiceProvider:

use Illuminate\Support\Facades\Schema;

/**
 * Загрузка любых служб приложения.
 */
public function boot(): void
{
    Schema::defaultStringLength(191);
}

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

Переименование индексов

Чтобы переименовать индекс, вы можете использовать метод renameIndex построителя схемы Blueprint. Этот метод принимает текущее имя индекса в качестве первого аргумента и желаемое имя в качестве второго аргумента:

$table->renameIndex('from', 'to')

Если ваше приложение использует базу данных SQLite, вы должны установить пакет doctrine/dbal с помощью менеджера пакетов Composer, прежде чем можно будет использовать метод renameIndex.

Удаление индексов

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

Команда Описание
$table->dropPrimary('users_id_primary'); Удалить первичный ключ из таблицы users.
$table->dropUnique('users_email_unique'); Удалить уникальный индекс из таблицы users.
$table->dropIndex('geo_state_index'); Удалить простой индекс из таблицы geo.
$table->dropFullText('posts_body_fulltext'); Удалить полнотекстовый индекс из таблицы posts.
$table->dropSpatialIndex('geo_location_spatialindex'); Удалить пространственный индекс из таблицы geo (кроме SQLite).

Если вы передадите массив столбцов в метод, удаляющий индексы, то обычное имя индекса будет сгенерировано на основе имени таблицы, столбцов и типа индекса:

Schema::table('geo', function (Blueprint $table) {
    $table->dropIndex(['state']); // Удалить простой индекс `geo_state_index`.
});

Ограничения внешнего ключа

Laravel также поддерживает создание ограничений внешнего ключа, которые используются для обеспечения ссылочной целостности на уровне базы данных. Например, давайте определим столбец user_id в таблице posts, который ссылается на столбец id в таблице users:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});

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

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
});

Метод foreignId создает столбец эквивалентный UNSIGNED BIGINT, в то время как метод constrained будет использовать соглашения для определения таблицы и столбца, на которые ссылаются. Если имя вашей таблицы не соответствует соглашениям Laravel, вы можете вручную указать его в методе constrained. Кроме того, можно также указать имя, которое должно быть присвоено созданному индексу:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained(
        table: 'users', indexName: 'posts_user_id'
    );
});

Вы также можете указать желаемое действие для свойств ограничения «при удалении» и «при обновлении»:

$table->foreignId('user_id')
      ->constrained()
      ->onUpdate('cascade')
      ->onDelete('cascade');

Для этих действий также предусмотрен альтернативный синтаксис выражений:

Метод Описание
$table->cascadeOnUpdate(); Обновления должны быть каскадными.
$table->restrictOnUpdate(); Обновления должны быть ограничены.
$table->cascadeOnDelete(); Удаления должны быть каскадными.
$table->restrictOnDelete(); Удаления должны быть ограничены.
$table->nullOnDelete(); Для удаления следует установить значение внешнего ключа равным null.

Любые дополнительные модификаторы столбца должны быть вызваны перед методом constrained:

$table->foreignId('user_id')
      ->nullable()
      ->constrained();

Удаление внешних ключей

Чтобы удалить внешний ключ, вы можете использовать метод dropForeign, передав в качестве аргумента имя ограничения внешнего ключа, которое нужно удалить. Ограничения внешнего ключа используют то же соглашение об именах, что и индексы. Другими словами, имя ограничения внешнего ключа основано на имени таблицы и столбцов в ограничении, за которым следует суффикс _foreign:

$table->dropForeign('posts_user_id_foreign');

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

$table->dropForeign(['user_id']);

Переключение ограничений внешнего ключа

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

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();

Schema::withoutForeignKeyConstraints(function () {
// Constraints disabled within this closure...
});

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

События

Для удобства каждая операция миграции отправляет событие. Все следующие события расширяют базовый класс Illuminate\Database\Events\MigrationEvent:

Класс Описание
Illuminate\Database\Events\MigrationsStarted Вот-вот будет выполнен пакет миграций.
Illuminate\Database\Events\MigrationsEnded Завершено выполнение пакета миграций.
Illuminate\Database\Events\MigrationStarted Одна миграция вот-вот будет выполнена.
Illuminate\Database\Events\MigrationEnded Выполнение одной миграции завершено.
Illuminate\Database\Events\SchemaDumped Завершена выгрузка схемы базы данных.
Illuminate\Database\Events\SchemaLoaded Загружена существующая выгрузка схемы базы данных.