如何将Laravel迁移转换为原始SQL脚本?

tvmytwxo  于 2023-05-30  发布在  其他
关注(0)|答案(5)|浏览(145)

我的团队的开发人员已经习惯了Laravel迁移的强大功能,他们在本地机器和我们的开发服务器上工作得很好。但是客户的数据库管理员不接受Laravel迁移。他要求为应用程序的每个新版本提供原始SQL脚本。

是否有任何工具或编程技术来捕获从Laravel迁移到向上/向下SQL脚本的输出?

如果在创建生产构建时,我们可以将SQL脚本生成集成到CI系统(TeamCity)中,那就太完美了。
顺便说一下,我们将在这个项目中使用Laravel 5和PostgreSQL。

58wvjzkj

58wvjzkj1#

更新2023-05-24 / Laravel 10

最近,我一直在使用这个一行程序来获取所有迁移的查询列表:
php artisan tinker --no-ansi --execute 'echo implode(PHP_EOL, array_reduce(glob("database/migrations/*.php"), fn($c, $i) => [...$c, ...array_column(app("db")->pretend(fn() => (include $i)->up()), "query")], []))'

使用migrate命令

在运行php artisan migrate将查询输出到终端时,可以添加--pretend标志:

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

此命令仅包括尚未迁移的迁移。

破解migrate命令

要进一步定制如何获取查询,请考虑破解源代码并创建自己的自定义命令或类似的东西。为了让您开始,这里有一些快速代码来获得所有迁移。

示例代码

$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")"
    ]
  ]
]

此代码将包括所有迁移。要了解如何只获取尚未迁移的内容,请查看vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php中的run()方法。

jdg4fx2g

jdg4fx2g2#

如果你遇到了和我一样的问题:
php artisan migrate --pretend
没有输出任何内容,但在没有将记录添加到迁移的情况下运行SQL。换句话说

  • 它执行SQL作业,这不是预期的
  • 我什么也没返回,这就是我打电话的原因
  • 我没有将条目添加到迁移中,这有点破坏了这种情况,因为我无法在不手动删除表的情况下重新运行迁移

原因是我设置了几个数据库,这些数据库是用
Schema::connection('master')->create('...
更多关于这个问题,你可以在这里找到:https://github.com/laravel/framework/issues/13431
可悲的是,一个Laravel开发人员关闭了这个问题,引用“* 关闭,因为这个问题似乎是一个罕见的边缘情况,可以用变通方法解决。对于我可能罕见的情况,我将使用第三方SQL差异检查器。
干杯

11dmarpk

11dmarpk3#

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

p4rjhz4m4#

我用的是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);
i5desfxk

i5desfxk5#

我不得不在--假装,改变这个:

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

相关问题