Генерация Laravel миграций из существующей базы данных

Источник: «Generate Laravel migrations from an existing database»
Одной из распространённых проблем при переносе легаси PHP-приложения на Laravel является создание миграции базы данных на основе существующей базы данных.

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

Как у программиста, у нас нет терпения, чтобы выполнять такую задачу, и мы не должны. Первая мысль — как это автоматизировать. Имя это ввиду, я искал существующее решение, нашёл несколько пакетов и выбрал один из них от kitloong, пакет генератор Laravel миграцииLaravel migration generator.

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

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

CREATE TABLE permissions
(
id bigint unsigned auto_increment primary key,
name varchar(255) not null,
guard_name varchar(255) not null,
created_at timestamp null,
updated_at timestamp null,
constraint permissions_name_guard_name_unique
unique (name, guard_name)
)
collate = utf8_unicode_ci;
CREATE TABLE roles
(
id bigint unsigned auto_increment primary key,
team_id bigint unsigned null,
name varchar(255) not null,
guard_name varchar(255) not null,
created_at timestamp null,
updated_at timestamp null,
constraint roles_team_id_name_guard_name_unique
unique (team_id, name, guard_name)
)
collate = utf8_unicode_ci;
CREATE TABLE role_has_permissions
(
permission_id bigint unsigned not null,
role_id bigint unsigned not null,
primary key (permission_id, role_id),
constraint role_has_permissions_permission_id_foreign
foreign key (permission_id) references permissions (id)
on delete cascade,
constraint role_has_permissions_role_id_foreign
foreign key (role_id) references roles (id)
on delete cascade
)
collate = utf8_unicode_ci;
CREATE INDEX roles_team_foreign_key_index on roles (team_id);

Установка пакета

composer require --dev kitloong/laravel-migrations-generator

Запуск команды пакета, которая творит чудеса

Вы можете указать или игнорировать определённые таблицы, используя --tables= или --ignore==, соответственно.

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

php artisan migrate:generate --tables="roles,permissions,role_permissions"

Вывод команды

Using connection: mysql

Generating migrations for: permissions,role_has_permissions,roles

Do you want to log these migrations in the migrations table? (yes/no) [yes]:
> yes

Setting up Tables and Index migrations.
Created: /var/www/html/database/migrations/2023_06_08_132125_create_permissions_table.php
Created: /var/www/html/database/migrations/2023_06_08_132125_create_role_has_permissions_table.php
Created: /var/www/html/database/migrations/2023_06_08_132125_create_roles_table.php

Setting up Views migrations.

Setting up Stored Procedures migrations.

Setting up Foreign Key migrations.
Created: /var/www/html/database/migrations/2023_06_08_132128_add_foreign_keys_to_role_has_permissions_table.php

Finished!

Проверка файлов миграции

Таблица Permissions : 2023_06_08_132125_create_permissions_table.php

...

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

$table->unsignedBigInteger('team_id')
->nullable()
->index('roles_team_foreign_key_index');

$table->string('name');
$table->string('guard_name');
$table->timestamps();

$table->unique(['team_id', 'name', 'guard_name']);
});

...

Таблица Roles: 2023_06_08_132125_create_roles_table.php

...

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

$table->unsignedBigInteger('team_id')
->nullable()
->index('roles_team_foreign_key_index');

$table->string('name');
$table->string('guard_name');
$table->timestamps();

$table->unique(['team_id', 'name', 'guard_name']);
});

...

Сводная таблица: 2023_06_08_132125_create_role_has_permissions_table.php

...

Schema::create('role_has_permissions', function (Blueprint $table) {
$table->unsignedBigInteger('permission_id');

$table->unsignedBigInteger('role_id')
->index('role_has_permissions_role_id_foreign');

$table->primary(['permission_id', 'role_id']);
});

...

Добавление внешнего ключа в сводную таблицу: 2023_06_08_132128_add_foreign_keys_to_role_has_permissions_table.php

...

Schema::table('role_has_permissions', function (Blueprint $table) {
$table->foreign(['permission_id'])
->references(['id'])
->on('permissions')
->onUpdate('NO ACTION')
->onDelete('CASCADE');

$table->foreign(['role_id'])
->references(['id'])
->on('roles')
->onUpdate('NO ACTION')
->onDelete('CASCADE');
});

...

Это лишь одна из проблем при переносе легаси PHP-приложения на Laravel.

Следующая статья будет о несовместимости алгоритма хэширования паролей.

Дополнительные материалы

Предыдущая Статья

Sass для веб-разработки

Следующая Статья

Безопасный способ использования переменных .env в Laravel