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_id
、foo_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 的文档中,不清楚如何做到这一点。在hasMany
和belongsTo
等其他关系中,我们可以指定local key
和foriegn key
,但由于某种原因不在此处。
我希望用户表上的local key
是bar_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 - Eager Loading BelongsToMany 关系