Миграции:

Содержание:


Введение

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

Фасад Ларавел Schema предоставляет поддержку базы данных для создания таблиц и проведения манипуляций с таблицами для всех поддерживаемых Laravel систем баз данных.


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

Чтобы создать миграцию, исопльзуйте команду Artisan 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 and down. Метод up используется для добавления новых таблиц, колонок или индексов для вашей базы данных, в то время метод down должен получать операции, представленные методом up.

Внутри обоих методов можно использовать конструктор схем Ларавел для выразитлеьного создания и изменения таблиц. Чтобы получить больше информации о всех методах доступных для конструктора Schema, обратитесь к документации. Например, этот пример миграции создаёт таблицу flights:

<?php

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

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');
    }
}

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

Для запуска всех ваших миграций выполните команду Artisan migrate:

php artisan migrate
Если вы используете Homestead, вам необходимо выполнять эти команды внутри вашей виртульаной машины.

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

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

php artisan migrate --force

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

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

php artisan migrate:rollback

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

php artisan migrate:rollback --step=5

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

php artisan migrate:reset

Откат и запуск миграций одной командой

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

php artisan migrate:refresh

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

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

php artisan migrate:refresh --step=5

Удалить все таблицы бд и запустить миграции

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

php artisan migrate:fresh

php artisan migrate:fresh --seed

Таблицы

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

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

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

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

Проверка на существование таблицы или колонки

Вы можете легко проверить, что таблица или столбез существуют используя методы 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');

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

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


Столбцы

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

Метод 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 с точностью (всего 8 цифр) и масштабом (2 знака после запятой).
$table->enum('level', ['easy', 'hard']); Эквивалент столбца ENUM
$table->float('amount', 8, 2); Эквивалент столбца FLOAT с точностью (всего 8 цифр) и масштабом (2 знака после запятой).
$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->multiPoint('positions'); Эквивалент столбца MULTIPOINT.
$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 столбца deleted_at TIMESTAMP для мягкого удаления.
$table->softDeletesTz(); Добавление nullable столбца deleted_at TIMESTAMP (с временной зоной) для мягкого удаления.
$table->string('name', 100); Эквивалент столбца VARCHAR с опциональной длиной.
$table->text('description'); Эквивалент столбца TEXT.
$table->time('sunrise'); Эквивалент столбца TIME.
$table->timeTz('sunrise'); Эквивалент столбца TIME (c временной зоной).
$table->timestamp('added_on'); Эквивалент столбца TIMESTAMP.
$table->timestampTz('added_on'); Эквивалент столбца TIMESTAMP (c временной зоной).
$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 equivalent column with a precision (total digits) and scale (decimal digits).
$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", вы можете использовать метод 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() Разместить столбец "first" в таблице (MySQL)
->nullable($value = true) Позволяет (по умолчанию) присвоить значение NULL столбцу
->storedAs($expression) Create a stored generated column (MySQL)
->unsigned() Установить INTEGER столбцы как UNSIGNED (MySQL)
->useCurrent() Указать столбцу TIMESTAMP использовать CURRENT_TIMESTAMP как базовое значение.
->virtualAs($expression) Создать виртуальную колонку (MySQL)
->generatedAs($expression) Создать identity-столбец с указанным набором опций (PostgreSQL)
->always() Определить приоритет последовательности значений для входящих данных для identity-столбецов (PostgreSQL).

Базовые выражения

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

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
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->json('movies')->default(new Expression('(JSON_ARRAY())'));
            $table->timestamps();
        });
    }
}
Поддержка для базовых выражений зависит от драйвера вашей базы данных, версии бд и от типа поля. Рекомендум обратиться к соответствующей документации для вашего конкретного случая. Также нужно понимать, что использование узкоспециализированных функций может вас сильно связать с одним из драйверов.

Модификация колонок

Предпосылки

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

composer require doctrine/dbal

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

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

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

Мы также сделать столбец nullable:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->nullable()->change();
});
Только следующие типы столбцов могут изменены: bigInteger, binary, boolean, date, dateTime, dateTimeTz, decimal, integer, json, longText, mediumText, smallInteger, string, text, time, unsignedBigInteger, unsignedInteger и unsignedSmallInteger.

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

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

Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('from', 'to');
});
Переименование любого столбца в таблице где есть тип enum не поддерживается.

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

Для удаления столбца, используйте метод 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']);
});
Удаление или модификация нескольких столбцов внутри одной миграции при использовании базы данных SQLite не поддерживается.

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

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

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

$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')

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

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

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

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

Schema::table('geo', function (Blueprint $table) {
    $table->dropIndex(['state']); // Drops index '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');
});

Вы также можете указать желаемое действие для свойств ограничения "on delete" и "on update":

$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();
SQLite отлкючает ограничения внешнего ключа по умолчанию. При использовании SQLite, убедитесь, что включили поддержку внешних ключей в конфигурации вашей базы данных до попытки создать их в ваших миграциях.