Laravel миграции базы данных

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

Фасад Laravel Schema обеспечивает создание и управления таблицами во всех поддерживаемых СУБД Laravel.

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

Создание новой миграции осуществляется командой make:migration

$ php artisan make:migration create_users_table

Новая миграция будет сохранена в директории database/migrations. Каждое имя файла миграции содержит метку времени, которая позволяет Laravel определять порядок миграций.

Для указания имени таблицы и того, будет ли миграция создавать новую таблицу можно использовать параметры --table и --create. Эти параметры предварительно заполняют сгенерированный файл миграции для указанной таблицы:

$ php artisan make:migration create_users_table --create=users

$ php artisan make:migration add_votes_to_users_table --table=users

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

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

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

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

<?php

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

class CreateFlightsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('flights');
    }
}

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

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

Принудительное выполнение миграции

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

$ php artisan migrate --force

Отмена миграций

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

$ php artisan migrate:rollback

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

$ php artisan migrate:rollback --step=5

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

$ php artisan migrate:reset

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

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

$ php artisan migrate:refresh

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

$ php artisan migrate:refresh --step=5

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

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

$ php artisan migrate:fresh

Таблицы

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

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

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

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

Проверка наличия таблицы / столбца

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

if (Schema::hasTable('users')) {
    //
}

if (Schema::hasColumn('users', 'email')) {
    //
}

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

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

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

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

Команда Описание
$table->engine = 'InnoDB'; Механизм хранения таблиц (MySQL).
$table->charset = 'utf8'; Набор символов по умолчанию для таблицы (MySQL).
$table->collation = 'utf8_unicode_ci'; Параметры сортировки по умолчанию для таблицы (MySQL).
$table->temporary(); Создание временной таблицы (кроме SQL Server).

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

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

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

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

Schema::drop('users');

Schema::dropIfExists('users');

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

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

Столбцы

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

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

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

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

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

Команда Описание
$table->bigIncrements('id'); Автоинкрементный столбец UNSIGNED BIGINT (первичный ключ)
$table->bigInteger('votes'); BIGINT столбец
$table->binary('data'); BLOB столбец
$table->boolean('confirmed'); BOOLEAN столбец
$table->char('name', 100); CHAR столбец с необязательной длиной
$table->date('created_at'); DATE столбец
$table->dateTime('created_at'); DATETIME столбец
$table->dateTimeTz('created_at'); DATETIME (с часовым поясом) столбец
$table->decimal('amount', 8, 2); DECIMAL столбец с точностью (общее количество цифр) и масштабом (десятичные цифры)
$table->double('amount', 8, 2); DOUBLE столбец с точностью (общее количество цифр) и масштабом (десятичные цифры)
$table->enum('level', ['easy', 'hard']); ENUM столбец.
$table->float('amount', 8, 2); FLOAT столбец с точностью (общее количество цифр) и масштабом (десятичные цифры)
$table->geometry('positions'); GEOMETRY столбец
$table->geometryCollection('positions'); GEOMETRYCOLLECTION столбец
$table->increments('id'); Автоинкрементный столбец UNSIGNED INTEGER (первичный ключ)
$table->integer('votes'); INTEGER столбец
$table->ipAddress('visitor'); Столбец IP-адреса
$table->json('options'); JSON столбец
$table->jsonb('options'); JSONB столбец
$table->lineString('positions'); LINESTRING столбец
$table->longText('description'); LONGTEXT столбец
$table->macAddress('device'); столбец MAC-адреса
$table->mediumIncrements('id'); Автоинкрементный столбец UNSIGNED MEDIUMINT (первичный ключ)
$table->mediumInteger('votes'); MEDIUMINT столбец
$table->mediumText('description'); MEDIUMTEXT столбец
$table->morphs('taggable'); Добавляет taggable_id UNSIGNED BIGINT и taggable_type VARCHAR столбцы
$table->uuidMorphs('taggable'); Добавляет taggable_id CHAR (36) и taggable_type VARCHAR (255) столбцы UUID
$table->multiLineString('positions'); MULTILINESTRING столбец
$table->multiPolygon('positions'); MULTIPOLYGON столбец
$table->nullableMorphs('taggable'); Добавляет nullable версию столбцов morphs()
$table->nullableUuidMorphs('taggable'); Добавляет nullable версию столбцов uuidMorphs()
$table->nullableTimestamps(); Псевдоним для метода timestamps()
$table->point('position'); POINT столбец
$table->polygon('positions'); POLYGON столбец
$table->rememberToken(); Добавляет nullable столбец remember_token VARCHAR (100)
$table->set('flavors', ['strawberry', 'vanilla']); SET столбец
$table->smallIncrements('id'); Автоинкрементный столбец UNSIGNED SMALLINT (первичный ключ)
$table->smallInteger('votes'); SMALLINT столбец
$table->softDeletes(); Добавляет nullable столбец TIMESTAMP для мягкого удаления
$table->softDeletesTz(); Добавляет nullable столбец TIMESTAMP (с часовым поясом) для мягкого удаления
$table->string('name', 100); VARCHAR столбец с необязательной длиной
$table->text('description'); TEXT столбец
$table->time('sunrise'); TIME столбец
$table->timeTz('sunrise'); TIME столбец (с часовым поясом)
$table->timestamp('added_on'); TIMESTAMP столбец
$table->timestampTz('added_on'); TIMESTAMP столбец (с часовым поясом)
$table->timestamps(); Добавляет nullable created_at и updated_at TIMESTAMP столбцы
$table->timestampsTz(); Добавляет nullable created_at и updated_at TIMESTAMP столбцы (с часовым поясом)
$table->tinyIncrements('id'); Автоинкрементный столбец UNSIGNED TINYINT (первичный ключ)
$table->tinyInteger('votes'); TINYINT столбец
$table->unsignedBigInteger('votes'); UNSIGNED BIGINT столбец
$table->unsignedDecimal('amount', 8, 2); UNSIGNED DECIMAL столбец с точностью (общее количество цифр) и масштабом (десятичные цифры)
$table->unsignedInteger('votes'); UNSIGNED INTEGER столбец
$table->unsignedMediumInteger('votes'); UNSIGNED MEDIUMINT столбец
$table->unsignedSmallInteger('votes'); UNSIGNED SMALLINT столбец
$table->unsignedTinyInteger('votes'); UNSIGNED TINYINT столбец
$table->uuid('id'); UUID столбец
$table->year('birth_year'); YEAR столбец

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

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

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

Ниже приведен список всех доступных модификаторов столбцов. Этот список не включает модификаторы индекса: |Модификатор|Описание| |-|-| |->after('column')|Помещает столбец «после» другого столбца (MySQL)| |->autoIncrement()|Устанавливает столбец INTEGER как автоинкремент (первичный ключ)| |->charset('utf8')|Указывает набор символов для столбца (MySQL)| |->collation('utf8_unicode_ci')|Указывает параметры кодировки для столбца (MySQL / PostgreSQL / SQL Server)| |->comment('my comment')|Добавляет комментарий к колонке (MySQL / PostgreSQL)| |->default($value)|Добавляет значение по умолчанию для столбца| |->first()|Помещает столбец «первым» в таблице (MySQL)| |->nullable($value = true)|Разрешает указывать NULL в качестве значения по-умолчанию| |->storedAs($expression)|Создает сохраненный сгенерированный столбец (MySQL)| |->unsigned()|Устанавливает для столбцов INTEGER значение UNSIGNED (MySQL)| |->useCurrent()|Указывает столбцу TIMESTAMP использовать текущее время в качестве значения по-умолчанию| |->virtualAs($expression)|Создает виртуальный сгенерированный столбец (MySQL)| |->generatedAs($expression)|Создает столбец идентификаторов с указанными параметрами последовательности (PostgreSQL)| |->always()|Определяет приоритет значений последовательности над вводом для столбца идентификаторов (PostgreSQL)|

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

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

  $ composer require doctrine/dbal

Обновление аттрибутов столбца

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

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

Мы также можем изменить столбец так, чтобы он мог принимать значение NULL:

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

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

Чтобы переименовать столбец, вы можете использовать метод renameColumn в построителе схемы. Перед переименованием столбца обязательно добавьте зависимость doctrine/dbal в ваш файл composer.json:

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

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

Чтобы удалить столбец, используйте метод dropColumn в построителе схемы. Прежде чем удалять столбцы из базы данных SQLite, вам нужно добавить зависимость doctrine/dbal в ваш файл composer.json и выполнить команду composer update в вашем терминале, чтобы установить библиотеку:

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

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

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

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

Команда Описание
$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()

Индексы

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

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

$table->string('email')->unique();

Кроме того, вы можете создать индекс после определения столбца. Например:

$table->unique('email');

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

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

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

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

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

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

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

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

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

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

$table->dropForeign('posts_user_id_foreign');

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

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

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

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();