{{TOC}} {{DOCVER 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51, 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15, 5.1=cdc24ba7426c5b11eb4d050706bd78c3ea4913cc 19.06.2016 20:08:01, 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11}} == Введение == Миграции - что-то вроде системы контроля версий для вашей базы данных. Они позволяют вашей команде изменять структуру БД, в то же время оставаясь в курсе изменений других участников. Миграции обычно идут рука об руку с ((docs/v5/schema построителем структур)) для более простого обращения с архитектурой вашей базы данных. Если вы когда-нибудь просили коллегу вручную добавить столбец в его локальную БД, значит вы сталкивались с проблемой, которую решают миграции БД. ((docs/v5/facades Фасад)) Laravel %%(t)Schema%% обеспечивает поддержку создания и изменения таблиц в независимости от используемой СУБД из числа тех, что поддерживаются в Laravel. == Создание миграций == Для создания новой миграции используйте ((/docs/v5/artisan Artisan))-команду %%(sh)make:migration%%: %%(sh) php artisan make:migration create_users_table %% Миграция будет помещена в папку %%(t)database/migrations%% и будет содержать метку времени, которая позволяет фреймворку определять порядок применения миграций. Можно также использовать параметры %%(t)--table%% и %%(t)--create%% для указания имени таблицы и того факта, что миграция будет создавать новую таблицу (!!(tl_note)а не изменять существующую - //прим. пер.//!!). Эти параметры просто заранее создают указанную таблицу в создаваемом файле-заглушке миграции: %%(sh) php artisan make:migration create_users_table --create=users php artisan make:migration add_votes_to_users_table --table=users %% Если вы хотите указать свой путь для сохранения создаваемых миграций, используйте параметр %%(t)--path%% при запуске команды %%(sh)make:migration%%. Этот путь должен быть указан относительно базового пути вашего приложения. == Структура миграций == Класс миграций содержит два метода: %%up()%% и %%down()%%. Метод %%up()%% используется для добавления новых таблиц, столбцов или индексов в вашу БД, а метод %%down()%% просто отменяет операции, выполненные методом %%up()%%. В обоих методах вы можете использовать построитель структур Laravel для удобного создания и изменения таблиц. О всех доступных методах построителя структур читайте в ((/docs/v5/migrations#создание_таблиц его документации)). Например, эта миграция создаёт таблицу %%(t)flights%%: %% increments('id'); $table->string('name'); $table->string('airline'); $table->timestamps(); }); } /** * Отмена миграций. * * @return void */ public function down() { Schema::drop('flights'); } } %% == Выполнение миграций == Для запуска всех необходимых вам миграций используйте Artisan-команду %%(sh)migrate%%. %%(sh) php artisan migrate %% .(alert) Если вы используете ((/docs/v5/homestead виртуальную машину Homestead)), вам надо выполнить эту команду на ВМ. %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15, 5.1=cdc24ba7426c5b11eb4d050706bd78c3ea4913cc 19.06.2016 20:08:01, 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11) Если при применении миграции вы получаете ошибку "class not found" ("класс не найден"), попробуйте выполнить команду %%(sh)composer dump-autoload%% и заново запустить команду %%(sh)migrate%%. %% **Принудительные миграции в продакшне** Некоторые операции миграций разрушительны, значит они могут привести к потере ваших данных. Для предотвращения случайного запуска этих команд на вашей боевой БД перед их выполнением запрашивается подтверждение. Для принудительного запуска команд без подтверждения используйте ключ %%(sh)--force%%: %%(sh) php artisan migrate --force %% === Откат миграций === Для отмены изменений, сделанных последней миграцией, используйте команду %%(sh)rollback%%. Эта команда отменит результат последней "партии" миграций, которая может включать несколько файлов миграций: %%(sh) php artisan migrate:rollback %% %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) Вы можете сделать откат определённого числа миграций, указав параметр %%(sh)step%% для команды %%(sh)rollback%%. Например, эта команда откатит последние пять миграций: %%(sh) php artisan migrate:rollback --step=5 ~%% %% Команда %%(sh)migrate:reset%% отменит изменения всех миграций вашего приложения: %%(sh) php artisan migrate:reset %% **Откат всех миграций и их повторное применение одной командой** Команда %%(sh)migrate:refresh%% отменит изменения всех ваших миграций, а затем выполнит команду %%(sh)migrate%%. Эта команда эффективно создаёт заново всю вашу БД: %%(sh) php artisan migrate:refresh // Обновить БД и запустить заполнение БД начальными данными... php artisan migrate:refresh --seed %% %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) Вы можете откатить и повторно применить определённое число миграций, указав параметр %%(sh)step%% для команды %%(sh)refresh%%. Например, эта команда откатит и повторно применит последние пять миграций: %%(sh) php artisan migrate:refresh --step=5 ~%% %% == Таблицы == === ((#создание_таблиц)) Создание таблиц === Для создания новой таблицы БД используйте метод %%create()%% фасада %%(t)Schema%%. Метод %%create()%% принимает два аргумента. Первый - имя таблицы, второй - замыкание, которое получает объект %%(t)Blueprint%%, который можно использовать для определения новой таблицы: %% Schema::create('users', function (Blueprint $table) { $table->increments('id'); }); %% Само собой, при создании таблицы вы можете использовать любые ((/docs/v5/migrations#создание_столбцов методы для работы со столбцами)) построителя структур. **Проверка существования таблицы/столбца** Вы можете легко проверить существование таблицы или столбца при помощи методов %%hasTable()%% и %%hasColumn()%%: %% if (Schema::hasTable('users')) { // } if (Schema::hasColumn('users', 'email')) { // } %% **Подключение и подсистема хранения данных** Если вы хотите выполнить операции над структурой через подключение к БД, которое не является вашим основным подключением, используйте метод %%connection()%%: %% Schema::connection('foo')->create('users', function (Blueprint $table) { $table->increments('id'); }); %% Используйте свойство %%(t)engine%% построителя структур, чтобы задать подсистему хранения данных для таблицы: %% Schema::create('users', function (Blueprint $table) { $table->engine = 'InnoDB'; $table->increments('id'); }); %% === Переименование/удаление таблиц === Для переименования существующей таблицы используйте метод %%rename()%%: %% Schema::rename($from, $to); %% Для удаления существующей таблицы используйте методы %%drop()%% и %%dropIfExists()%%: %% Schema::drop('users'); Schema::dropIfExists('users'); %% %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15) **Переименование таблиц с внешними ключами** Перед переименованием таблицы вы должны проверить, что для всех ограничений внешних ключей таблицы есть явные имена в файлах вашей миграции, чтобы избежать автоматического назначения имён на основе принятого соглашения. Иначе имя ограничения внешнего ключа будет ссылаться на имя старой таблицы. %% == Столбцы == === ((#создание_столбцов)) Создание столбцов === Для изменения существующей таблицы мы будем использовать метод %%table()%% фасада %%(t)Schema%%. Как и метод %%create()%%, метод %%table()%% принимает два аргумента: имя таблицы и замыкание, которое получает экземпляр %%(t)Blueprint%%, который можно использовать для добавления столбцов в таблицу: %% Schema::table('users', function (Blueprint $table) { $table->string('email'); }); %% **Доступные типы столбцов** Разумеется, построитель структур содержит различные типы столбцов, которые вы можете указывать при построении ваших таблиц: %%(hvlraw)
Команда Описание
$table->bigIncrements('id');Инкрементный ID (первичный ключ), использующий эквивалент "UNSIGNED BIG INTEGER"
$table->bigInteger('votes');Эквивалент BIGINT для базы данных
$table->binary('data');Эквивалент BLOB для базы данных
$table->boolean('confirmed');Эквивалент BOOLEAN для базы данных
$table->char('name', 4);Эквивалент CHAR для базы данных
$table->date('created_at');Эквивалент DATE для базы данных
$table->dateTime('created_at');Эквивалент DATETIME для базы данных
$table->dateTimeTz('created_at');Эквивалент DATETIME (с часовым поясом) для базы данных (для версии 5.2 и выше)
$table->decimal('amount', 5, 2);Эквивалент DECIMAL с точностью и масштабом
$table->double('column', 15, 8);Эквивалент DOUBLE с точностью, всего 15 цифр, после запятой 8 цифр
$table->enum('choices', ['foo', 'bar']);Эквивалент ENUM для базы данных
$table->float('amount', 8, 2);Эквивалент FLOAT для базы данных, всего 8 знаков, из них 2 после запятой (для версии 5.3 и выше)
$table->float('amount');Эквивалент FLOAT для базы данных (для версии 5.2 и ранее)
$table->increments('id');Инкрементный ID (первичный ключ), использующий эквивалент "UNSIGNED INTEGER"
$table->integer('votes');Эквивалент INTEGER для базы данных
$table->ipAddress('visitor');Эквивалент IP-адреса для базы данных (для версии 5.2 и выше)
$table->json('options');Эквивалент JSON для базы данных
$table->jsonb('options');Эквивалент JSONB для базы данных
$table->longText('description');Эквивалент LONGTEXT для базы данных
$table->macAddress('device');Эквивалент MAC-адреса для базы данных (для версии 5.2 и выше)
$table->mediumIncrements('id');Инкрементный ID (первичный ключ), использующий эквивалент "UNSIGNED MEDIUM INTEGER" (для версии 5.3 и выше)
$table->mediumInteger('numbers');Эквивалент MEDIUMINT для базы данных
$table->mediumText('description');Эквивалент MEDIUMTEXT для базы данных
$table->morphs('taggable');Добавление столбца taggable_id INTEGER (для версии 5.3 и выше Unsigned INTEGER) и taggable_type STRING
$table->nullableMorphs('taggable');Аналогично morphs(), но разрешено значение NULL (для версии 5.3 и выше)
$table->nullableTimestamps();Аналогично timestamps(), но разрешено значение NULL
$table->rememberToken();Добавление столбца remember_token VARCHAR(100) NULL
$table->smallIncrements('id');Инкрементный ID (первичный ключ), использующий эквивалент "UNSIGNED SMALL INTEGER" (для версии 5.3 и выше)
$table->smallInteger('votes');Эквивалент SMALLINT для базы данных
$table->softDeletes();Добавление столбца deleted_at для мягкого удаления (для версии 5.3 и выше разрешено значение NULL)
$table->string('email');Эквивалент VARCHAR
$table->string('name', 100);Эквивалент VARCHAR с длинной
$table->text('description');Эквивалент TEXT для базы данных
$table->time('sunrise');Эквивалент TIME для базы данных
$table->timeTz('sunrise');Эквивалент TIME (с часовым поясом) для базы данных (для версии 5.2 и выше)
$table->tinyInteger('numbers');Эквивалент TINYINT для базы данных
$table->timestamp('added_on');Эквивалент TIMESTAMP для базы данных
$table->timestampTz('added_on');Эквивалент TIMESTAMP (с часовым поясом) для базы данных (для версии 5.2 и выше)
$table->timestamps();Добавление столбцов created_at и updated_at (для версии 5.3 и выше разрешено значение NULL)
$table->timestampsTz();Добавление столбцов created_at и updated_at (с часовым поясом), для которых разрешено значение NULL (для версии 5.3 и выше)
$table->unsignedBigInteger('votes');Эквивалент Unsigned BIGINT для базы данных (для версии 5.3 и выше)
$table->unsignedInteger('votes');Эквивалент Unsigned INT для базы данных (для версии 5.3 и выше)
$table->unsignedMediumInteger('votes');Эквивалент Unsigned MEDIUMINT для базы данных (для версии 5.3 и выше)
$table->unsignedSmallInteger('votes');Эквивалент Unsigned SMALLINT для базы данных (для версии 5.3 и выше)
$table->unsignedTinyInteger('votes');Эквивалент Unsigned TINYINT для базы данных (для версии 5.3 и выше)
$table->uuid('id');Эквивалент UUID для базы данных
%% === Модификаторы столбцов === Вдобавок к перечисленным типам столбцов существует несколько "модификаторов" столбцов, которые вы можете использовать при добавлении столбцов в таблицу. Например, чтобы сделать столбец "обнуляемым", используйте метод %%nullable()%%: %% Schema::table('users', function (Blueprint $table) { $table->string('email')->nullable(); }); %% Ниже перечислены все доступные модификаторы столбцов. В этом списке отсутствуют ((/docs/v5/migrations#создание_индексов модификаторы индексов)): %%(hvlraw)
Модификатор Описание
->after('column')Помещает столбец "после" указанного столбца (только MySQL)
->comment('my comment')Добавляет комментарий в столбец (для версии 5.2 и выше)
->default($value)Указывает значение "по умолчанию" для столбца
->first()Помещает столбец "первым" в таблице (только MySQL)
->nullable()Разрешает вставлять значения NULL в столбец
->storedAs($expression)Создать генерируемый столбец типа stored (только MySQL) (для версии 5.3 и выше)
->unsigned()Делает столбцы integer беззнаковыми UNSIGNED
->virtualAs($expression)Создать генерируемый столбец типа virtual (только MySQL) (для версии 5.3 и выше)
%% === Изменение столбцов === **Требования** Перед изменением столбцов добавьте зависимость %%(t)doctrine/dbal%% в свой файл %%(t)composer.json%%. Библиотека Doctrine DBAL используется для определения текущего состояния столбца и создания SQL-запросов, необходимых для выполнения указанных преобразований столбца: %%(sh) composer require doctrine/dbal %% **Изменение атрибутов столбца** Метод %%change()%% позволяет изменить тип существующего столбца или изменить его атрибуты. Например, если вы захотите увеличить размер строкового столбца %%(t)name%% с 25 до 50: %% Schema::table('users', function (Blueprint $table) { $table->string('name', 50)->change(); }); %% Также мы можем изменить столбец, чтобы он стал "обнуляемым": %% Schema::table('users', function (Blueprint $table) { $table->string('name', 50)->nullable()->change(); }); %% %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) .(alert) Столбы следующих типов нельзя "изменить": %%(t)char, double, enum, mediumInteger, timestamp, tinyInteger, ipAddress, json, jsonb, macAddress, mediumIncrements, morphs, nullableMorphs, nullableTimestamps, softDeletes, timeTz, timestampTz, timestamps, timestampsTz, unsignedMediumInteger, unsignedTinyInteger, uuid%%. %% %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15) .(alert) Пока не поддерживается изменение любых столбцов в таблице, содержащей столбцы типов %%(t)enum%%, %%(t)json%% или %%(t)jsonb%%. %% **Переименование столбцов** Для переименования столбца используйте метод %%renameColumn()%% на построителе структур. Перед переименованием столбца добавьте зависимость %%(t)doctrine/dbal%% в свой файл %%(t)composer.json%%: %% Schema::table('users', function (Blueprint $table) { $table->renameColumn('from', 'to'); }); %% .(alert) Пока не поддерживается переименование любых столбцов в таблице, содержащей столбцы типов %%(t)enum%%, а для версий 5.2 и ранее ещё и %%(t)json%% или %%(t)jsonb%%. === Удаление столбцов === Для удаления столбца используйте метод %%dropColumn()%% на построителе структур. Перед удалением столбцов из базы данных SQLite вам необходимо добавить зависимость %%(t)doctrine/dbal%% в ваш файл %%(t)composer.json%% и выполнить команду %%(sh)composer update%% для установки библиотеки: %% Schema::table('users', function (Blueprint $table) { $table->dropColumn('votes'); }); %% Вы можете удалить несколько столбцов таблицы, передав массив их имён в метод %%dropColumn()%%: %% Schema::table('users', function (Blueprint $table) { $table->dropColumn(['votes', 'avatar', 'location']); }); %% .(alert) Удаление и изменение нескольких столбцов одной миграцией не поддерживается для базы данных SQLite. == Индексы == === ((#создание_индексов)) Создание индексов === Построитель структур поддерживает несколько типов индексов. Сначала давайте посмотрим на пример, в котором задаётся, что значения столбца должны быть уникальными. Для создания индекса мы можем просто сцепить метод %%unique()%% с определением столбца: %% $table->string('email')->unique(); %% Другой вариант - создать индекс после определения столбца. Например: %% $table->unique('email'); %% Вы можете даже передать массив столбцов в метод %%index()%% для создания сложного индекса: %% $table->index(['account_id', 'created_at']); %% %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15) Laravel автоматически генерирует подходящее имя индекса, но вы можете передать своё значение вторым аргументом метода: ~%% $table->index('email', 'my_index_name'); ~%% %% **Доступные типы индексов** %%(hvlraw)
Команда Описание
$table->primary('id');Добавление первичного ключа
$table->primary(['first', 'last']);Добавление составных ключей
$table->unique('email');Добавление уникального индекса
$table->unique('state', 'my_index_name');Добавление своего имени индекса (для версии 5.2 и выше)
$table->unique(['first', 'last']);Добавление составного уникального индекса (для версии 5.3 и выше)
$table->index('state');Добавление базового индекса
%% === Удаление индексов === Для удаления индекса необходимо указать его имя. По умолчанию Laravel автоматически назначает имена индексам. Просто соедините имя таблицы, имя столбца-индекса и тип индекса. Вот несколько примеров: %%(hvlraw)
Команда Описание
$table->dropPrimary('users_id_primary');Удаление первичного ключа из таблицы "users"
$table->dropUnique('users_email_unique');Удаление уникального индекса из таблицы "users"
$table->dropIndex('geo_state_index');Удаление базового индекса из таблицы "geo"
%% Если вы передадите массив столбцов в метод для удаления индексов, будет сгенерировано стандартное имя индекса на основе имени таблицы, столбца и типа ключа: %% Schema::table('geo', function (Blueprint $table) { $table->dropIndex(['state']); // Удаление индекса 'geo_state_index' }); %% === Ограничения внешнего ключа === Laravel также поддерживает создание ограничений для внешнего ключа, которые используются для обеспечения ссылочной целостности на уровне базы данных. Например, давайте определим столбец %%(t)user_id%% в таблице %%(t)posts%%, который ссылается на столбец %%(t)id%% в таблице %%(t)users%%: %% Schema::table('posts', function (Blueprint $table) { $table->integer('user_id')->unsigned(); $table->foreign('user_id')->references('id')->on('users'); }); %% Вы также можете указать требуемое действие для свойств %%(t)"on delete"%% и %%(t)"on update"%% ограничений: %% $table->foreign('user_id') ->references('id')->on('users') ->onDelete('cascade'); %% Для удаления внешнего ключа используйте метод %%dropForeign()%%. Ограничения внешнего ключа используют те же принципы именования, что и индексы. Итак, мы соединим имя таблицы и столбцов из ограничения, а затем добавим суффикс %%(t)"_foreign"%%: %% $table->dropForeign('posts_user_id_foreign'); %% Либо вы можете передать значение массива, при этом для удаления будет автоматически использовано стандартное имя ограничения: %% $table->dropForeign(['user_id']); %% %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15) Вы можете включить или выключить ограничения внешнего ключа в своих миграциях с помощью следующих методов: ~%% Schema::enableForeignKeyConstraints(); Schema::disableForeignKeyConstraints(); ~%% %% %%(DOCNEW 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11) == ((#начальные)) Загрузка начальных данных в БД == Кроме миграций, описанных выше, Laravel также включает в себя механизм наполнения вашей БД начальными данными (//seeding//) с помощью специальных классов. Все такие классы хранятся в %%(t)database/seeds%%. Они могут иметь любое имя, но вам, вероятно, следует придерживаться какой-то логики в их именовании - например, %%UserTableSeeder%% и т.д. По умолчанию для вас уже определён класс %%DatabaseSeeder%%. Из этого класса вы можете вызывать метод %%call()%% для подключения других классов с данными, что позволит вам контролировать порядок их выполнения. **Пример класса для загрузки начальных данных** ~%% class DatabaseSeeder extends Seeder { public function run() { $this->call('UserTableSeeder'); $this->command->info('Таблица пользователей загружена данными!'); } } class UserTableSeeder extends Seeder { public function run() { DB::table('users')->delete(); User::create(['email' => 'foo@bar.com']); } } ~%% Для добавления данных в БД используйте Artisan-команду %%(sh)db:seed%%: %%(sh) php artisan db:seed ~%% По умолчанию команда **db:seed** вызывает класс %%DatabaseSeeder%%, который может быть использован для вызова других классов, заполняющих БД данными. Однако, вы можете использовать параметр %%(sh)--class%% для указания конкретного класса для вызова: %%(sh) php artisan db:seed --class=UserTableSeeder ~%% Вы также можете использовать для заполнения БД данными команду %%(sh)migrate:refresh%%, которая также откатит и заново применит все ваши миграции: %%(sh) php artisan migrate:refresh --seed ~%% %%