Laravel 外键 onDelete('cascade') 不起作用

Posted

技术标签:

【中文标题】Laravel 外键 onDelete(\'cascade\') 不起作用【英文标题】:Laravel foreign key onDelete('cascade') not workingLaravel 外键 onDelete('cascade') 不起作用 【发布时间】:2014-09-13 20:37:18 【问题描述】:

我在用户和角色之间有一个多对多的关系,有一个 role_user 表。我的迁移设置如下(简化):

users表:

public function up()

    Schema::create('users', function(Blueprint $table)
    
        $table->increments('id');
        $table->string('email')->unique();
    );

roles表:

public function up()

    Schema::create('roles', function(Blueprint $table)
    
        $table->increments('id');
        $table->string('name');
    );

role_user表:

public function up()

    Schema::create('role_user', function(Blueprint $table)
    
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->integer('role_id')->unsigned();
        $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
    );

因此,根据文档,我将外键设置为无符号。

现在,我添加了几个用户,并附加了一些角色 - 一切正常。但是,当我删除一个用户 (User::destroy(2)) 时,role_user 表中该用户的行不会被删除,这会导致冗余行。

我做错了什么?

mysql + InnoDB

编辑:抓取模型并应用->delete(); 也有相同的效果。

【问题讨论】:

您是否在 MySQL 中创建了关系?在 phpMyAdmin 等软件中检查您的表结构。也尝试删除$table->integer('user_id')->unsigned(); 我安装了 PHPMyAdmin - 我在哪里查看关系?会有一个公牛。 binarytides.com/blog/wp-content/uploads/2009/08/… 这可能会有所帮助 那里什么都没有。令人困惑...迁移期间没有抛出错误。 好的,我手动设置了$table->engine = 'InnoDB';,现在它可以工作了,即使它在数据库的“类型”列下显示“InnoDB”。很奇怪。 【参考方案1】:

尝试创建此表时尝试设置。这个修复对我有用。

$table->engine = 'InnoDB';

我在以下位置提交了一个错误:https://github.com/laravel/framework/issues/8730

【讨论】:

这个问题很可能是因为你的 MySQL 实例中的默认表引擎设置为不支持外键的 MyISAM。尝试在 MyISAM 表上使用外键绝对不是 Laravel 中的错误。虽然如果使用外键,Schema Builder 可以自动将引擎设置为 InnoDB,那就太好了。 确保将其添加到所有迁移中,否则将无法正常工作。 谁还在使用 MyISAM :)【参考方案2】:

Jake 的回答表明您已将默认引擎设置为 InnoDB

$table->engine = 'InnoDB';

您可以在config/database.php 中这样做,而不是在每个迁移文件中这样做

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => false,
        'engine' => 'InnoDB',
    ],

【讨论】:

要添加到 Shreyansh 的答案,这更快,但您需要重新启动 localhost:8000 然后运行 ​​php artisan migrate:fresh 当然要先备份您的数据。【参考方案3】:

我知道这是一个老问题,但最近(在 Laravel 8 上)我在使用 InnoDB 时也遇到了同样的问题。

我通过在关系上使用 constrained() 选项解决了这个问题。如果没有“约束”参数,迁移不会在数据库上创建实际关系。

$table->foreignId('user_id')->constrained()->onDelete('cascade');

【讨论】:

【参考方案4】:

检查 MySQL 配置。 my.ini 可能仍有default-storage-engine=MYISAM。设置为default-storage-engine=InnoDB,您应该避免在每次迁移中添加此修复程序的麻烦。

【讨论】:

在 Windows 和 WAMP 下的本地开发机器上更改 my.ini 后,不要忘记重新启动 WAMP 服务(左键单击任务栏图标并选择 重新启动所有服务【参考方案5】:

对于在这里并在他们的模型上使用SoftDeletes 的人;使用 SoftDeletes 时,onDelete('cascade') 功能丢失。在这种情况下您可以使用的选项是:

    使用dyrynda/laravel-cascade-soft-deletes 包为您处理此问题。 使用Eloquent Events触发父行已被删除的事件,并自行处理子行的删除。

【讨论】:

【参考方案6】:

即使在 Config->Database 中将引擎更改为 InnoDB 它不起作用

解决方案是改变迁移

来自

Schema::create('users', function (Blueprint $table) $table->BigIncrements('id');

Schema::create('users', function (Blueprint $table) $table->increments('id');

【讨论】:

我真的不认为将BigIncrements 更改为increments 是一个理想的答案。 bigInteger 方法创建一个 BIGINT 等效列,increments 方法创建一个自动递增的 UNSIGNED INTEGER 等效列作为主键。

以上是关于Laravel 外键 onDelete('cascade') 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 迁移 onDelete() 查询异常

Eloquent - 如果外键有行,则防止删除数据 - Laravel

MySQL外键约束OnDelete和OnUpdate的使用

Laravel 权限管理总结

Laravel Migrations onDelete Restrict 不起作用

多列外键:将单列设置为 Null “ON DELETE”而不是全部