Как преобразовать миграции Laravel в необработанные сценарии SQL?

Разработчики из моей команды действительно привыкли к миграции Laravel, они отлично работают на локальных машинах и наших серверах разработчиков. Но администратор базы данных клиента не примет миграцию Laravel. Он запрашивает необработанные сценарии SQL для каждой новой версии нашего приложения.

Существует ли какой-либо инструмент или методика программирования для захвата результатов миграции Laravel в сценарии SQL вверх / вниз?

Было бы идеально, если бы мы могли интегрировать генерацию сценариев SQL в нашу систему CI (TeamCity) при создании производственных сборок.

Кстати, мы будем использовать Laravel 5 и PostgreSQL для этого проекта.

2 ответа

Решение

Используйте команду migrate

Вы можете добавить --pretend флаг, когда вы бежите php artisan migrate для вывода запросов в терминал:

php artisan migrate --pretend

Это будет выглядеть примерно так:

Migration table created successfully.
CreateUsersTable: create table "users" ("id" integer not null primary key autoincrement, "name" varchar not null, "email" varchar not null, "password" varchar not null, "remember_token" varchar null, "created_at" datetime not null, "updated_at" datetime not null)
CreateUsersTable: create unique index users_email_unique on "users" ("email")
CreatePasswordResetsTable: create table "password_resets" ("email" varchar not null, "token" varchar not null, "created_at" datetime not null)
CreatePasswordResetsTable: create index password_resets_email_index on "password_resets" ("email")
CreatePasswordResetsTable: create index password_resets_token_index on "password_resets" ("token")

Чтобы сохранить это в файл, просто перенаправьте вывод без ansi:

php artisan migrate --pretend --no-ansi > migrate.sql

Эта команда включает только те миграции, которые еще не были перенесены.


Взломать команду переноса

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

Пример кода

$migrator = app('migrator');
$db = $migrator->resolveConnection(null);
$migrations = $migrator->getMigrationFiles('database/migrations');
$queries = [];

foreach($migrations as $migration) {
    $migration_name = $migration;
    $migration = $migrator->resolve($migration);

    $queries[] = [
        'name' => $migration_name,
        'queries' => array_column($db->pretend(function() use ($migration) { $migration->up(); }), 'query'),
    ];
}

dd($queries);

Пример вывода

array:2 [
  0 => array:2 [
    "name" => "2014_10_12_000000_create_users_table"
    "queries" => array:2 [
      0 => "create table "users" ("id" integer not null primary key autoincrement, "name" varchar not null, "email" varchar not null, "password" varchar not null, "remember_token" varchar null, "created_at" datetime not null, "updated_at" datetime not null)"
      1 => "create unique index users_email_unique on "users" ("email")"
    ]
  ]
  1 => array:2 [
    "name" => "2014_10_12_100000_create_password_resets_table"
    "queries" => array:3 [
      0 => "create table "password_resets" ("email" varchar not null, "token" varchar not null, "created_at" datetime not null)"
      1 => "create index password_resets_email_index on "password_resets" ("email")"
      2 => "create index password_resets_token_index on "password_resets" ("token")"
    ]
  ]
]

Этот код будет включать все миграции. Чтобы увидеть, как получить только то, что еще не перенесено, взгляните на run() метод в vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php,

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

php artisan migrate --pretend

ничего не выводил, но запускает SQL без добавления записи в миграцию. Другими словами,

  • это делает работу SQL, которая не была предназначена
  • ничего не вернул, поэтому я и позвонил
  • не добавлял запись в миграции, что разрушает ситуации, так как я не смог перезапустить миграцию без удаления таблиц вручную

Причиной этого была моя настройка с несколькими базами данных, которые адресованы

Schema::connection('master')->create('...

Больше по этому вопросу вы можете найти здесь: https://github.com/laravel/framework/issues/13431

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

ура

Код user2479930 отличный, но я получал:

Class 'LocalItemsSchema.php' not found

Я отладил проблему и исправил ее следующим образом:

foreach($migrations as $migration) {
        $migration_name = $migration;
        $migration_name = str_replace('.php', '', $migration_name);
        $migration = $migrator->resolve($migration_name);

        $queries[] = [
            'name' => $migration_name,
            'queries' => array_column($db->pretend(function() use ($migration) { $migration->up(); }), 'query'),
        ];
    }

Я использую Laravel 6.X. Для меня ответ @user2479930 не сработал. Мне нужно было прочитать исходный код Migrator и добавить:$migrator->requireFiles($migrations); чтобы он работал.

$migrator = app('migrator');
$db = $migrator->resolveConnection(null);
$migrations = $migrator->getMigrationFiles('database/migrations');
$migrator->requireFiles($migrations);
$queries = [];

foreach ($migrations as $migration) {
    $migration_name = $migration;
    $migration = $migrator->resolve($migrator->getMigrationName($migration_name));

    $queries[] = [
        'name' => $migration_name,
        'queries' => array_column($db->pretend(function () use ($migration) {
            $migration->up();
        }), 'query'),
    ];
}
dd($queries);

Мне пришлось сделать это после --pretend, измените это:

CreateTablenameTable: create table `tablename` (`id` bigint unsigned not null auto_increment primary key, `code` varchar(255) not null, `valeur` varchar(255) not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci' engine = InnoDB
CreateTablenameTable: alter table `tablename` add unique `tablename_code_unique`(`code`)

К этому:

create table tablename 
(
id bigint unsigned not null auto_increment primary key, 
code varchar(255) not null, 
valeur varchar(255) not null
) default character set utf8mb4 collate 'utf8mb4_unicode_ci' engine = InnoDB;
alter table tablename add unique tablename_code_unique(code);
Другие вопросы по тегам