如何让 php artisan:migrate 运行一组动态的 SQL 脚本?

How can I have php artisan:migrate run a dynamic set of SQL scripts?

提问人:ChaseMedallion 提问时间:11/4/2023 更新时间:11/4/2023 访问量:40

问:

我有一个 laravel 应用程序,它使用通过原始 SQL 脚本而不是 php 迁移迁移的数据库。

对于本地开发和测试,我想将这些脚本挂接到.我想要的行为是,每次有人运行时,laravel 都会收集脚本并运行所有以前没有运行过的脚本。php artisan migratephp artisan migrate

一种方法是为每个脚本创建一个 php 迁移文件,但我想知道我是否可以挂接到收集迁移文件的过程以动态执行此操作。

我尝试注册我自己的 in 实例,但这似乎不起作用。MigratorAppServiceProvider

php sql laravel 数据库迁移

评论

0赞 Adi 11/4/2023
您可以尝试使用 make:command 创建命令。因此,无需向 AppServiceProvider 注册它。然后,在命令文件中添加逻辑以运行脚本,并在内核文件中注册该命令。
0赞 Tim Lewis 11/4/2023
我认为你最好为每个脚本创建一个迁移,并让 Laravel 运行它们(并跟踪哪些脚本已经运行)。迁移完全能够在模式生成器中运行原始 SQL,而不是使用模式生成器。就我个人而言,我不知道有什么方法可以挂钩到该过程,因为它使用文件名和批号来跟踪哪些迁移已运行和尚未运行。up()down()

答:

0赞 Jeyhun Rashidov 11/4/2023 #1
  • 首先,创建一个自定义 Artisan 命令,该命令将处理原始 SQL 脚本的执行:
php artisan make:command RunSqlMigrations
  • 将 SQL 脚本放在特定目录中,并遵循允许您跟踪已执行的脚本的命名约定,例如在文件名中包含时间戳或版本号。
  • 使用数据库中的表来跟踪已运行的脚本。这与 Laravel 的迁移表的工作方式类似。
  • 在自定义命令中:
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;

class RunSqlMigrations extends Command
{
    protected $signature = 'migrate:sql';
    protected $description = 'Run raw SQL migrations';

    public function handle()
    {
        $sqlDirectory = database_path('sql_migrations');
        $files = File::allFiles($sqlDirectory);

        foreach ($files as $file) {
            $filename = $file->getFilename();

            if ($this->alreadyRun($filename)) {
                $this->info("Skipping: {$filename}");
                continue;
            }

            try {
                DB::unprepared(File::get($file->getPathname()));
                $this->recordAsRun($filename);
                $this->info("Migrated: {$filename}");
            } catch (\Exception $e) {
                $this->error("Failed to migrate: {$filename}");
                return;
            }
        }
    }

    protected function alreadyRun($filename)
    {
        return DB::table('sql_migrations')->where('filename', $filename)->exists();
    }

    protected function recordAsRun($filename)
    {
        DB::table('sql_migrations')->insert(['filename' => $filename, 'migrated_at' => now()]);
    }
}
  • 在 Console/Kernel.php 中注册您的新命令,以便它可用作 Artisan 命令。
  • 您可以通过运行以下命令来使用它:
php artisan migrate:sql
  • 如果要在命令中运行原始 SQL 迁移,则可以扩展 或侦听事件(如果可用),并在正常迁移完成后触发 SQL 迁移。php artisan migrateMigrateCommandMigrationsEnded

PS:我从我的旧项目中获取了这些代码。您可以根据需要对其进行修改。

评论

0赞 ChaseMedallion 11/10/2023
这是制作一个自定义命令,而不是挂钩到 php artisan migrate,对吧?