如何在 Laravel 中使用两个foreignId

h-k*_*kys 2 php database laravel

我有两个表,例如:

用户:

Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('loginid')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
Run Code Online (Sandbox Code Playgroud)

IP:

Schema::create('i_p_s', function (Blueprint $table) {
        $table->id();
        $table->string('address')->unique();

        $table->foreignId('user_id')->nullable();
        $table->string('hostname');
        $table->string('description')->nullable();
        $table->timestamps();

        $table->index('user_id');
    });
Run Code Online (Sandbox Code Playgroud)

IP型号:

public function User() {
    return $this->belongsTo(User::class);
}
Run Code Online (Sandbox Code Playgroud)

用户型号:

public function IPs() {
    return $this->hasMany(IP::class);
}
Run Code Online (Sandbox Code Playgroud)

user_id列表示该 IP 正在由哪个用户使用。

现在我想添加一个新列last_modified,这意味着谁是该行的最后一个编辑者。

所以我认为也last_modified应该如此$table->foreignId('user_id')->nullable();

但如何定义IP模型中的关系呢?

user_id另外,我现在这样称呼它。

$ips = IP::with('user')->get();

@foreach ($ips as $ip)
    {{ $ip->user }}
@endforeach
Run Code Online (Sandbox Code Playgroud)

last_modified那么如何在定义之后调用呢?

多谢

Dan*_*naq 7

如文档(https://laravel.com/docs/7.x/migrations#foreign-key-constraints)所示,

$table->foreignId('user_id')->nullable();
Run Code Online (Sandbox Code Playgroud)

只是“老”路的捷径

Schema::table('i_p_s', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});
Run Code Online (Sandbox Code Playgroud)

您的代码的问题是,您还需要 -constrained()方法。它将把给定的列名称溶解user_id为“Laravel,请在此处使用表的列”idusers
我不确定nullable()- 方法是否可用于此快捷方式。

同样,你的关系也将溶解在你的模型中。如果您没有向belongsTo()andhaveMany()方法添加其他值,Laravel 将尝试通过假定主键和表名称的标准命名约定(如果模型中未设置表名称)来尝试在数据库中找到方法。

  • 主键假定为id。这也是行之有效的原因$table->ip()
  • 表名称假定为模型名称的复数形式。这还意味着,您必须确保i_p_s在 IP 模型中设置表的名称,因为它不遵循约定。更好的做法是考虑适应惯例并致电您的餐桌ips
  • 外键应该(能够以这种方式解决问题)由单数表名、下划线、主键命名。换句话说user_id

因此,除了您无法添加名为 的第二列这一事实之外,您的假设应该是正确的user_id。对于第二个外键,您的代码应该看起来像“正常/传统”的执行方式。

Schema::table('i_p_s', function (Blueprint $table) {
    $table->unsignedBigInteger('last_modified')->nullable();

    $table->foreign('last_modified')->references('id')->on('users');
});
Run Code Online (Sandbox Code Playgroud)

我很确定这会起作用,尽管我还没有测试过。不幸的是,我不确定您是否可以在受约束的方法中提供列名和表。如果是这样的话,那就非常方便了。尝试一下,否则就用传统方法。

模型内的关系应如下所示:

public function hasChanged() {
    $this->hasMany(IP::class, 'last_modified', 'id');
}
Run Code Online (Sandbox Code Playgroud)

last_modified是表中的外键i_p_s,而id是您拥有的模型的本地列User

对于 IP 模型来说,将其反过来:

public function wasChangedBy() {
    $this->belongsTo(User::class, 'last_modified', 'id');
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都可以不必将“id”列设置为表的主键,users因为它是标准的。

由于构造/架构的原因,关系与您的示例中的相同。在 99% 的情况下,这始终是一对多关系。

最后但并非最不重要的一点是,看到同一个外键的这种构造在同一个表中两次引用有点奇怪。但我发现了这篇文章,它说这样做最终是完全正常的。
Mysql:对同一个表使用两个外键

我能想到的唯一其他方法是在i_p_s和之间有一个中间表users,但这会导致数据库中这两个表之间出现循环,这也是您应该避免的事情。所以我想说这没关系。

希望这可以帮助 ;)