Laravel belongsToMany 关系在两个表上定义本地键

Posted

技术标签:

【中文标题】Laravel belongsToMany 关系在两个表上定义本地键【英文标题】:Laravel belongsToMany relationship defining local key on both tables 【发布时间】:2014-08-15 00:26:19 【问题描述】:

所以belongsToMany关系是多对多关系,所以需要数据透视表

例如,我们有一个users 表和一个roles 表和一个user_roles 数据透视表。

数据透视表有两列,user_idfoo_id...foo_id 指的是角色表中的id

为此,我们在user eloquent 模型中编写以下代码:

return $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');

现在这会在users 表中查找id 字段,并将其与user_roles 表中的user_id 字段连接。

问题是我想指定一个不同的字段,而不是 id 以加入 users 表。例如,我在 users 表中有 bar_id,我想将其用作 local key 以加入 user_id

从 laravel 的文档中,不清楚如何做到这一点。在hasManybelongsTo 等其他关系中,我们可以指定local keyforiegn key,但由于某种原因不在此处。

我希望用户表上的local keybar_id 而不仅仅是id

我该怎么做?

【问题讨论】:

【参考方案1】:

更新: 从 Laravel 5.5 开始,可以使用泛型关系方法,如下面的@cyberfly 所述:

public function categories()

    return $this->belongsToMany(
         Category::class,
         'service_categories',
         'service_id',
         'category_id', 
         'uuid',  // new in 5.5
         'uuid'   // new in 5.5
    );


供参考,以前的方法:

我假设 id 是您的 User 模型上的主键,因此无法使用 Eloquent 方法执行此操作,因为 belongsToMany 使用 $model->getKey() 来获取该键。

因此,您需要创建扩展 belongsToMany 的自定义关系,这将满足您的需求。

您可以尝试的快速猜测:(未经测试,但肯定不适用于预加载)

// User model
protected function setPrimaryKey($key)

  $this->primaryKey = $key;


public function roles()

  $this->setPrimaryKey('desiredUserColumn');

  $relation = $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');

  $this->setPrimaryKey('id');

  return $relation;

【讨论】:

这会影响其他关系吗? 如果你的意思是调整,那么没有。除了我猜的这种关系,它不会影响任何事情。 这似乎在获取时起作用。但是当我附加时,它附加的是 id 而不是我的desiredUserColumn。我该如何解决? 仅使用自定义关系类。那一栏是什么,为什么你仍然需要这样的功能? 我正在导入数据,所有的关系都是用另一个键设置的,除了 'id' 键。所以现在我需要确保这些关系正确完成。【参考方案2】:

在 Laravel 5.5 及更高版本上,

    public function categories()
    
        return $this->belongsToMany(Category::class,'service_categories','service_id','category_id', 'uuid', 'uuid');
    

来自源代码:

    public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
                                  $parentKey = null, $relatedKey = null, $relation = null)
    

【讨论】:

哪个 L5?不在我的 L5.4 中。 无法编辑,所以添加:不是 L5。 L5.5(或 L5.6)。之前不可用 效果很好,正是我想要的。【参考方案3】:

我最近遇到了同样的问题,我需要一个关联表,该表使用 ID 将两个不是主键的表链接在一起。基本上我所做的是创建模型的副本,该模型对数据透视表进行建模并将主键设置为我希望它使用的值。我尝试创建一个模型实例,设置主键,然后将其传递给关系,但 Laravel 不尊重我设置的主键(使用上面的 ->setPrimaryKey() 方法)。

复制模型并设置主键感觉有点“hackish”,但最终它可以正常工作,而且由于数据透视表模型通常很小,我认为它不会导致任何问题未来。

希望在 Laravel 的下一个版本中看到第三个关键选项,让您的链接更加具体。

【讨论】:

【参考方案4】:

belongsToMany 允许定义将在数据透视表中存储 che 键的字段的名称该方法始终插入 主键 将值添加到这些字段中。

你必须:

在方法belongsToMany中定义表和列;

然后使用受保护的 $primaryKey = 'local_key';您可以选择哪个值存储。

【讨论】:

【参考方案5】:

最好的办法是设置主键。

class Table extends Eloquent 

     protected $table = 'table_name';

     protected $primaryKey = 'local_key';

【讨论】:

【参考方案6】:

这是最近添加的功能。我不得不升级到 4.1,因为我也在寻找这个。

来自API documentation:

public BelongsToMany belongsToMany(string $related, string $table = null, string $foreignKey = null, string $otherKey = null, string $relation = null)

$otherKey$relation 参数是在 4.1 中添加的。使用$foreignKey$otherKey 参数可以指定关系两边的键。

【讨论】:

以上是关于Laravel belongsToMany 关系在两个表上定义本地键的主要内容,如果未能解决你的问题,请参考以下文章

Laravel belongsToMany 关系只有一个结果

Laravel 递归 whereHas on BelongsToMany 关系

Laravel 4 belongsToMany 关系返回空

Laravel - Eager Loading BelongsToMany 关系

检查 belongsToMany 关系是不是存在 - Laravel

Laravel 多对多关系( hasMany 或 belongsToMany )