IO7 Migrations
Внимание
Данная статья документации написана нейросетью. Возможны некоторые расхождения и неточность информации!
Обзор
IO7 предоставляет Laravel-совместимый API для миграций базы данных. Миграции позволяют версионировать структуру БД и легко воспроизводить изменения.
Создание миграции
php iocli make:migration create_users_table
Создаёт файл в app/Migrations/ с именем {timestamp}_create_users_table.php.
Опции
| Опция | Описание |
|---|---|
--module=<name> | Создать в модуле вместо app |
--factory | Также создать фабрику |
--seeder | Также создать сидер |
--class | Также создать SqlClass модель |
--api | Также создать API класс |
--all | Создать всё (фабрика, сидер, модель, API) |
Конвенции имён
| Имя миграции | Тип | Таблица |
|---|---|---|
create_users_table | create | users |
add_email_to_users_table | update | users |
drop_users_table | drop | users |
API миграций
Schema
Класс IO\Database\Schema\Schema предоставляет статический API для работы со схемой БД.
use IO\Database\Schema\Schema;
use IO\Database\Schema\Blueprint;
// Создать таблицу
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->boolean('is_deleted')->default(false);
$table->timestamps();
});
// Изменить таблицу
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->nullable()->after('email');
});
// Удалить таблицу
Schema::dropIfExists('users');
// Переименовать таблицу
Schema::rename('old_name', 'new_name');
// Проверки
Schema::hasTable('users'); // bool
Schema::hasColumn('users', 'email'); // bool
Schema::hasIndex('users', 'email'); // bool
Schema::getColumnListing('users'); // array
Blueprint
Класс IO\Database\Schema\Blueprint предоставляет fluent API для определения колонок.
Типы колонок
// Идентификаторы
$table->id(); // bigIncrements('id')
$table->increments('id'); // unsigned auto-increment int
$table->bigIncrements('id'); // unsigned auto-increment bigint
// Целые числа
$table->integer('count');
$table->unsignedInteger('count');
$table->bigInteger('amount');
$table->smallInteger('status');
$table->tinyInteger('flag');
// Десятичные
$table->decimal('price', 8, 2);
$table->float('rate');
$table->double('value');
// Строки
$table->string('name', 255); // VARCHAR
$table->char('code', 4); // CHAR
$table->text('description'); // TEXT
$table->mediumText('content'); // MEDIUMTEXT
$table->longText('body'); // LONGTEXT
// Логический
$table->boolean('is_active');
// Дата/Время
$table->date('birthday');
$table->dateTime('created_at');
$table->timestamp('logged_at');
$table->timestamps(); // created_at + updated_at
$table->softDeletes(); // deleted_at
// JSON/Бинарные
$table->json('metadata');
$table->jsonb('settings'); // PostgreSQL jsonb
$table->binary('file_data');
// UUID/ULID
$table->uuid('uuid');
$table->ulid('ulid');
// Перечисления
$table->enum('status', ['active', 'inactive']);
$table->set('tags', ['php', 'js', 'python']);
// Сетевые
$table->ipAddress('ip');
$table->macAddress('mac');
Модификаторы колонок
$table->string('email')->nullable();
$table->string('name')->default('unknown');
$table->integer('age')->unsigned();
$table->string('code')->unique();
$table->string('title')->after('id');
$table->string('slug')->first();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrentOnUpdate();
$table->string('email')->comment('Email пользователя');
$table->decimal('total')->storedAs('price * quantity');
$table->string('full_name')->virtualAs("CONCAT(first_name, ' ', last_name)");
Индексы
$table->primary('id');
$table->unique('email');
$table->index('status');
$table->fullText('description'); // MySQL FULLTEXT
$table->spatialIndex('location'); // MySQL SPATIAL
// Составные индексы
$table->unique(['provider', 'provider_id']);
$table->index(['user_id', 'created_at']);
Внешние ключи
// Через foreignId + constrained
$table->foreignId('user_id')->constrained();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
// Через foreign
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
$table->foreign('user_id')->references('id')->on('users')->nullOnDelete();
// Действия при удалении/обновлении
->cascadeOnDelete() // CASCADE
->restrictOnDelete() // RESTRICT
->nullOnDelete() // SET NULL
->cascadeOnUpdate() // CASCADE
->restrictOnUpdate() // RESTRICT
Морфы (полиморфные связи)
$table->morphs('commentable'); // commentable_type + commentable_id
$table->nullableMorphs('commentable'); // nullable версия
$table->uuidMorphs('commentable'); // UUID версия
$table->ulidMorphs('commentable'); // ULID версия
Удаление/Переименование
$table->dropColumn('description');
$table->dropColumn(['field1', 'field2']);
$table->renameColumn('old_name', 'new_name');
$table->dropPrimary('users_pkey');
$table->dropUnique('users_email_unique');
$table->dropIndex('users_status_index');
$table->dropForeign('posts_user_id_foreign');
Выполнение миграций
Запуск всех миграций
php iocli migrate
Откат последнего батча
php iocli migrate:rollback
Статус миграций
php iocli migrate:status
Полный сброс и перезапуск
php iocli migrate:fresh
Примеры
Создание таблицы пользователей
<?php
declare(strict_types=1);
namespace App\Migrations;
use IO\Database\Migrations\Migration;
use IO\Database\Schema\Schema;
use IO\Database\Schema\Blueprint;
class CreateUsersTable extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->string('phone')->nullable();
$table->boolean('is_active')->default(true);
$table->boolean('is_deleted')->default(false);
$table->timestamp('last_login_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
}
Создание таблицы с внешними ключами
<?php
declare(strict_types=1);
namespace App\Migrations;
use IO\Database\Migrations\Migration;
use IO\Database\Schema\Schema;
use IO\Database\Schema\Blueprint;
class CreatePostsTable extends Migration
{
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->text('body');
$table->enum('status', ['draft', 'published', 'archived'])->default('draft');
$table->boolean('is_deleted')->default(false);
$table->timestamps();
$table->index('status');
$table->index(['user_id', 'status']);
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
}
Добавление колонки к существующей таблице
<?php
declare(strict_types=1);
namespace App\Migrations;
use IO\Database\Migrations\Migration;
use IO\Database\Schema\Schema;
use IO\Database\Schema\Blueprint;
class AddPhoneToUsersTable extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->nullable()->after('email');
$table->index('phone');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropIndex('phone');
$table->dropColumn('phone');
});
}
}
Удаление таблицы
<?php
declare(strict_types=1);
namespace App\Migrations;
use IO\Database\Migrations\Migration;
use IO\Database\Schema\Schema;
class DropOldTableTable extends Migration
{
public function up(): void
{
Schema::dropIfExists('old_table');
}
public function down(): void
{
// Восстановить таблицу при откате
}
}
Структура файлов
modules/io7/php/Database/
├── Migrations/
│ └── Migration.php # Базовый класс миграций
├── Schema/
│ ├── Schema.php # Фасад для работы со схемой
│ ├── Blueprint.php # Определение колонок и индексов
│ ├── ColumnDefinition.php # Модификаторы колонок
│ ├── ForeignKeyDefinition.php
│ └── ForeignIdColumnDefinition.php
├── Migration.php # Обратная совместимость (наследует Migrations\Migration)
├── TableBuilder.php # Построитель таблиц (legacy)
└── SqlConnection.php # Подключение к БД