Laravel :: 更新外键的最佳方法

Posted

技术标签:

【中文标题】Laravel :: 更新外键的最佳方法【英文标题】:Laravel :: Best way to update a foreign key 【发布时间】:2016-11-20 12:38:55 【问题描述】:

我有这个迁移文件

Schema::create('table_one', function(Blueprint $table) 
 
    $table->increments('id'); 
    $table->string('name'); 
    $table->integer('table_two_id')->unsigned(); 
    $table->foreign('table_two_id')->references('id')->on('table_two'); 
    $table->timestamps(); 
);

我想更新以使其 ->onDelete('cascade');

$table->foreign('table_two_id')->references('id')->on('table_two')->onDelete('cascade');

最好的方法是什么?

有没有类似 ->change();

谢谢

【问题讨论】:

【参考方案1】:

删除外键,然后再次添加并运行迁移。

public function up()

    Schema::table('table_one', function (Blueprint $table) 
        $table->dropForeign(['table_two_id']);

        $table->foreign('table_two_id')
            ->references('id')
            ->on('table_two')
            ->onDelete('cascade');
    );

【讨论】:

这确实是有道理的,因为 mysql 会以同样的方式做,在这种情况下 MySQL 没有“变化”。但是,对于这种情况,我希望在 Laravel 级别上有一个 wrapper/single_command。谢谢。 有数据不能删除,如何重新获取数据?在这种情况下,应该创建一个新列,然后制作一个脚本将数据从旧列复制到新列,然后将其删除,但这不是最好的方法,这是我的观点。我们可以安装:composer 需要学说/dbal 然后轻松更改它: $table->foreignId('table_two_id') ->nullable()->change()【参考方案2】:

Christopher K. 是对的,在 Laravel 文档中说:

要删除外键,您可以使用 dropForeign 方法。外键约束使用与索引相同的命名约定。因此,我们将连接表名和约束中的列,然后在名称后面加上“_foreign”

$table->dropForeign('posts_user_id_foreign'); 

或者,您可以传递一个 array 值,该值将在删除时自动使用常规约束名称:

$table->dropForeign(['user_id']);

https://laravel.com/docs/5.7/migrations#foreign-key-constraints

【讨论】:

感谢您的回答,但是这种命名约定既不是强制性的,也不可靠。我不断达到 foreign_key_name_length 的限制并重命名不重命名依赖外键的列。所以我对@Borut Flis 的回答很满意。【参考方案3】:
    composer require doctrine/dbal 在您的迁移文件中,执行以下操作:
    Schema::table('table_one', function (Blueprint $table) 
        $table->foreignId('table_two_id')
              ->change()
              ->constrained('table_two')
              ->onDelete('cascade');
    );
    php artisan migrate

【讨论】:

通过重新定义constrained更新外键时会出现错误SQLSTATE[23000]: Integrity constraint violation: 1022 Can't write; duplicate key in table...,因此只需删除约束并说一些您只需要更新并与->change()链接的内容。在我的情况下,我刚刚更新了一个可以为空的外键,我不需要再次重新定义约束,因为它应该在创建迁移中调用,而不是改变一个,除非你想将约束更改为另一个表.【参考方案4】:

你需要删除

     public function up()
    
        Schema::table('<tableName>', function (Blueprint $table) 
            $table->dropForeign('<FK-name>');
            $table->dropColumn('<FK-columnName>');
        );
        Schema::table('<tableName>', function (Blueprint $table) 
            $table->foreignId('<FK-columnName>')->constrained()->cascadeOnDelete();
        );

    

有两个查询。在 Laravel 8 上工作

【讨论】:

【参考方案5】:

如何通过控制器进行

1- 设置一个 Rought: 路线::get('foreignkeyforimg', "foreignkey@index"); 2- 使用外键名称创建控制器。 3- 从迁移类扩展的外键控制器。 4- 转到数据库并从表中手动删除旧的主键

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class Foreignkey extends Migration

    function index()

        Schema::table('images', function (Blueprint $table) 


            $table->foreign('sub_cat_id')
               ->references('id')
                ->on('subcategories')
                ->onDelete('cascade');
        );
    

【讨论】:

你能解释一下为什么有人应该使用控制器来做到这一点吗? “转到数据库并删除”是什么意思?如果您为这些东西编写迁移,为什么要手动运行? 因为,通过迁移,可能会伤害到其他数据库表。这是更新任何表的外键的简单方法。这对新手来说非常简单 请通过编辑您的答案进一步解释:您所说的“伤害”是什么意思?大多数主要的 PHP 脚本在迁移中运行这样的东西,我从来没有听说过更改索引会伤害任何数据库 你的函数不会更新,而是创建一个外键,如果外键存在它就不起作用。问题是关于更新外键。 读取点 4... 4- 转到数据库并从表中手动删除旧的主键

以上是关于Laravel :: 更新外键的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 如何将外键用于具有识别外键的表?

没有外键的laravel关系

具有自定义外键的 Laravel 多态

Laravel - Eloquent - 获得没有外键的关系

复合键的 Laravel 验证

Laravel 5.4 - 删除外键的唯一约束时出错[重复]