Maybe I'm implementing wrong. Maybe I'm doing things I'm not supposed to do, but conceptually I think I'm okay.
I have two models, one is Users
, other is Communities
, and since it is a many to many relationship I need an intermediate table, Laravel calls them a pivot table. According to Laravel recommendations it is named communities_users
Normally, the pivot tables only contain the id's to the main tables. But I need a bit more data. Check this image, the migrations are done to match this diagram:
Here I have a role
in the pivot table. Lets say a user belongs to two communities, one as community's president, other as a member.
Of course the president
will have more capabilities than the member
, for example, he can accept a pending
person to become a member
person, or he can promote a member to a deputy
status or so...
Now lets say I want to get the names of the people with deputy
role on a given community. I can easily do that using the Query Builder, by joining the three tables and applying where('communities_users.role', 'deputy')
,
Now, what if I want to use the ORM and get the whole User
model?
I'd like to have a function on the Community so it gives me the users
of a given role
, maybe:
public function users($role) {
...
}
So I can do things like:
$community = Community::find($id);
foreach ($community->users('deputy') as user) {
...
echo user->name; // or whatever
...
}
Is it possible? How?
答案 0 :(得分:2)
正如您所说,数据透视表上只会显示模型键:
默认情况下,只有模型关键点会出现在枢轴对象上。 如果数据透视表包含其他属性,则必须指定它们 在定义关系时:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
因此,为了在查询相关记录时使用其他字段,您需要告诉Laravel您正在中间/数据透视表中存储更多列:
// Community.php
public function users()
{
return $this->belongsToMany(User::class)
->withPivot('role'); // <---
}
现在您可以得到所需的输出:
$community = Community::find($id);
$deputies = $community->users()->wherePivot('role', '=', 'deputy')->get();
foreach ($deputies as $deputy)
{
echo $deputy->name;
}
阅读文档的this section。
您说:
...根据Laravel建议,其名称为
communities_users
...
起初,我虽然可以,因为您的模型似乎具有多个名称(我说的是模型名称,而不是表名称)。但是随后,在所需的输出中,您使用了Community
来引用模型。因此,我将在文档的Many to Many部分中引用以下内容:
多对多
要定义此关系,需要三个数据库表:
users
,roles
和role_user
。role_user
表是派生的 从相关模型名称的字母顺序开始,并且包含user_id
和role_id
列。
如您所见,一般约定是按照相关模型中的字母顺序命名中间表,但以单数命名,因此在您的情况下为community_user
。
这是Laravel使用的惯例,因为您可以通过将中间表名称作为附加参数传递来覆盖关系定义中的名称。
答案 1 :(得分:1)
Hiding under the Many To Many section of the Eloquent relationship docs:
Filtering Relationships Via Intermediate Table Columns
You can also filter the results returned by
belongsToMany
using thewherePivot
andwherePivotIn
methods when defining the relationship:
return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);
Assuming your Communities model already has a belongsToMany
relationship set up for Users, you should be able to do something like:
$deputies = $community->users()
->wherePivot('role', 'deputy') // or equivalent value
->get();
答案 2 :(得分:1)
首先,您必须像这样定义模型之间的关系:
您告诉您在用户中拥有用户模型,
public function communities(){
return $this->belongsToMany(Communities::class, 'communities_users','user_id', 'community_id');
}
并在您的社区模型中:
public function users(){
return $this->belongsToMany(Users::class, 'communities_users','community_id','user_id')
->withPivot("role");
}
现在您可以像这样访问控制器中的任何角色类型用户:
$community = Community::find($id);
$deputies = $community->users()
->wherePivot('role', 'deputy') // by passing different role
->get();
foreach ($deputies as $deputy)
{
echo $deputy->name; // print names
}