导致错误的Laravel Migrations不会回滚

Tro*_*oso 6 database laravel-4

我发现,在Laravel中构建我的数据库模式时,失败的迁移不会回滚,这会使迁移变得毫无意义.

例如,我有这个迁移:

Schema::create('accounts', function(Blueprint $table)
{
    $table->increments('act_id');

    $table->string('act_name', 50)->unique();
    $table->boolean('act_active')->default(1);
    $table->unsignedInteger('act_type');
    $table->unsignedInteger('act_businesstype')->default(1);

    $table->timestamps();
});

Schema::table('accounts', function($table)
{
    $table->foreign('act_businesstype')->references('bst_id')->on('businesstypes');
});
Run Code Online (Sandbox Code Playgroud)

无论如何,如果我运行该迁移,表创建就好了,但是外键失败并且我收到错误.没关系.我应该得到一个错误.但是,常识让我假设如下:

  1. 由于迁移失败,更改应自动回滚.好吧,他们没有.

可以,然后呢

  1. 我应该调用migrate:rollback来撤消这些更改.好吧,没有发生迁移的记录,所以我最终还是回滚了之前发生的迁移.

我在这里做错了吗?我弄清楚如何"撤消"失败的迁移的唯一方法是实际进入数据库并删除表.在处理复杂的架构时,这是非常令人沮丧的,我会来回修复错误.

所以,我想我现在已经有了我的小咆哮,我的问题是:

如何回滚抛出错误的迁移?

Tro*_*oso 4

几年后回到这个问题,现在对数据库的工作原理有了更多的了解:

迁移无法“自动回滚”。无法在事务中执行架构更改。只有 INSERTS、UPDATES 和 DELETES 可以回滚。

为了使其正常工作,需要有一个等效的“drop”脚本,该脚本在发生错误时运行以恢复架构更改。

编辑:看来这个问题仍然受到一些关注,所以我想链接 Larvel 关于如何构建迁移文件的文档:https://laravel.com/docs/10.x/migrations#migration-struct,并且我'将在此处发布代码以供后代使用,以及如何处理错误的调整:

<?php
 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        try {
            Schema::create('flights', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->string('airline');
                $table->timestamps();
            });
        } catch (Exception $e) {
            $this->down();
            throw $e;
        }
    }
 
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('flights');
    }
};
Run Code Online (Sandbox Code Playgroud)

因此,down如果您选择手动回滚迁移或发生错误,该函数将执行。

Schema::dropIfExists最后要注意的是函数中的使用down。对于此特定迁移,如果Schema::create调用失败,则不会创建表。这意味着没有可删除的表。dropIfExists防止在这种情况下出现额外的错误。