In Laravel, how can I access data from a pivot table?

时间:2019-04-17 00:44:28

标签: php laravel

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:

enter image description here

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?

3 个答案:

答案 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部分中引用以下内容:

  

多对多

     

要定义此关系,需要三个数据库表:   usersrolesrole_userrole_user表是派生的   从相关模型名称的字母顺序开始,并且包含   user_idrole_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 the wherePivot and wherePivotIn 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
}