简体   繁体   English

在Laravel中,如何从数据透视表访问数据?

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

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. 我有两个模型,一个是Users ,另一个是Communities ,并且由于这是多对多关系,因此我需要一个中间表,Laravel称它们为数据透视表。 According to Laravel recommendations it is named communities_users 根据Laravel的建议,它被命名为communities_users

Normally, the pivot tables only contain the id's to the main tables. 通常,数据透视表仅包含主表的ID。 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. 在这里,我在数据透视表中role了一个role 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... president当然比member拥有更多的能力,例如,他可以接受pending人员成为member ,或者可以将会员提升为deputy身份等等。

Now lets say I want to get the names of the people with deputy role on a given community. 现在说我想获得给定社区中具有deputy角色的人员的姓名。 I can easily do that using the Query Builder, by joining the three tables and applying where('communities_users.role', 'deputy') , 我可以使用查询生成器轻松地做到这一点,方法是联接三个表并应用where('communities_users.role', 'deputy')

Now, what if I want to use the ORM and get the whole User model? 现在,如果我想使用ORM并获得整个User模型怎么办?

I'd like to have a function on the Community so it gives me the users of a given role , maybe: 我想在社区中使用某个功能,以便为我提供指定roleusers ,也许是:

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? 怎么样?

As you said only the model keys will be present on the pivot table: 如您所说,数据透视表上只会显示模型键:

By default, only the model keys will be present on the pivot object. 默认情况下,只有模型关键点会出现在枢轴对象上。 If your pivot table contains extra attributes, you must specify them when defining the relationship: 如果数据透视表包含额外的属性,则在定义关系时必须指定它们:

 return $this->belongsToMany('App\\Role')->withPivot('column1', 'column2'); 

So, in order to use additional fields when querying related records you need to tell Laravel that you are storing more columns in your intermediate/pivot table: 因此,为了在查询相关记录时使用其他字段,您需要告诉Laravel您正在中间/数据透视表中存储更多列:

// Community.php

public function users()
{
    return $this->belongsToMany(User::class)
                ->withPivot('role'); // <---
}

Now you can get your desired output: 现在您可以获得所需的输出:

$community = Community::find($id);
$deputies = $community->users()->wherePivot('role', '=', 'deputy')->get();

foreach ($deputies as $deputy)
{
    echo $deputy->name;
}

Read this section of the documentation. 阅读文档的此部分


Observation 意见

You said: 你说:

... according to Laravel recommendations it is named communities_users ... ...根据Laravel的建议,它被命名为communities_users ...

At first, I though that this was ok since your models appear to have names in plural (I'm talking about model name, not table name). 起初,我虽然可以,因为您的模型似乎具有多个名称(我说的是模型名称,而不是表名称)。 but then, in your desired output you used Community to refer to a model. 但是随后,在所需的输出中,您使用了Community来引用模型。 So I'm gonna quote this from the Many to Many section of the documentation: 因此,我将在文档的“ 多对多”部分中引用以下内容:

Many To Many 多对多

To define this relationship, three database tables are needed: users , roles , and role_user . 要定义这种关系,需要三个数据库表: usersrolesrole_user The role_user table is derived from the alphabetical order of the related model names, and contains the user_id and role_id columns. role_user表是从相关模型名称的字母顺序得出的,并且包含user_idrole_id列。

As you see, the general convention is to name the intermediate table in alphabetic order from the related model but in singular , so in your case: community_user . 如您所见,一般约定是从相关模型中按字母顺序命名中间表,但以单数命名,因此在您的情况下为: community_user

This is the convention that Laravel uses, of couse you can just override the name in the relationship definition passing the intermadiate table name as an additional argument. 这是Laravel使用的惯例,因为您可以通过将中间表名称作为附加参数传递来覆盖关系定义中的名称。

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: 在定义关系时,您还可以使用wherePivotwherePivotIn方法过滤belongsToMany返回的结果:

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: 假设您的社区模型已经为用户设置了一个belongsToMany关系,那么您应该能够执行以下操作:

$deputies = $community->users()
    ->wherePivot('role', 'deputy') // or equivalent value
    ->get();

First you have to define relationship between models like this : 首先,您必须像这样定义模型之间的关系:

you told that you have Users model then in Users: 您告诉您在“用户”中拥有“用户”模型:

public function communities(){
    return $this->belongsToMany(Communities::class, 'communities_users','user_id', 'community_id');
}

and In your Communities model : 在您的社区模型中:

public function users(){
    return $this->belongsToMany(Users::class, 'communities_users','community_id','user_id')
     ->withPivot("role");
}

Now you can access any role type users in your controllers like this : 现在,您可以像这样访问控制器中的任何角色类型用户:

$community = Community::find($id);
$deputies = $community->users()
->wherePivot('role', 'deputy') // by passing different role
->get();

foreach ($deputies as $deputy)
{
    echo $deputy->name; // print names
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM