如何将 Laravel 迁移转换为原始 SQL 脚本?
How to convert Laravel migrations to raw SQL scripts?
我团队的开发人员真的习惯了 Laravel 迁移的强大功能,他们在本地机器和我们的开发服务器上工作得很好。
但是客户的数据库管理员不会接受 Laravel 迁移。他要求为我们应用程序的每个新版本提供原始 SQL 脚本。
是否有任何工具或编程技术可以捕获从 Laravel 迁移到 up/down SQL 脚本的输出?
如果我们可以在创建生产构建时将 SQL 脚本生成集成到我们的 CI 系统 (TeamCity) 中,那就太完美了。
顺便说一下,我们将在这个项目中使用 Laravel 5 和 PostgreSQL。
使用迁移命令
您可以在 运行 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
This command only include the migrations that hasn't been migrated yet.
破解迁移命令
要进一步自定义获取查询的方式,请考虑破解源代码并制作您自己的自定义命令或类似命令。为了帮助您入门,这里有一些快速代码来获取所有迁移。
示例代码
$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")"
]
]
]
This code will include all the migrations. To see how to only get what isn't already migrated take a look at the run()
method in vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php
.
以防你遇到和我一样的问题:
php artisan migrate --pretend
没有输出任何东西,但是 运行s 和 SQLs 没有将记录添加到迁移中。换句话说,
- 它执行 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);
我团队的开发人员真的习惯了 Laravel 迁移的强大功能,他们在本地机器和我们的开发服务器上工作得很好。 但是客户的数据库管理员不会接受 Laravel 迁移。他要求为我们应用程序的每个新版本提供原始 SQL 脚本。
是否有任何工具或编程技术可以捕获从 Laravel 迁移到 up/down SQL 脚本的输出?
如果我们可以在创建生产构建时将 SQL 脚本生成集成到我们的 CI 系统 (TeamCity) 中,那就太完美了。
顺便说一下,我们将在这个项目中使用 Laravel 5 和 PostgreSQL。
使用迁移命令
您可以在 运行 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
This command only include the migrations that hasn't been migrated yet.
破解迁移命令
要进一步自定义获取查询的方式,请考虑破解源代码并制作您自己的自定义命令或类似命令。为了帮助您入门,这里有一些快速代码来获取所有迁移。
示例代码
$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")"
]
]
]
This code will include all the migrations. To see how to only get what isn't already migrated take a look at the
run()
method invendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php
.
以防你遇到和我一样的问题:
php artisan migrate --pretend
没有输出任何东西,但是 运行s 和 SQLs 没有将记录添加到迁移中。换句话说,
- 它执行 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);