简体   繁体   English

Laravel/Eloquent - 通过 BelongsToMany 关系建模 HasOne 关系

[英]Laravel/Eloquent - Modeling a HasOne relationship via a BelongsToMany relationship

Say I have four tables:假设我有四张桌子:

  • users用户
  • groups团体
  • activities活动
  • group_activities group_activity

Where a group can have any number of activities and an activity can belong to any number of groups through their intermediate table group_activities , and a user belongs to one group via users.group_id .一个组可以有任意数量的activities ,一个活动可以通过它们的中间表group_activities属于任意数量的groups ,并且一个用户通过users.group_id属于一个组。 I want to correctly model a relationship between users and activities so that a user can have any one activity, but only if the group that user belongs to has a relation to that activity.我想正确地 model usersactivities之间的关系,以便用户可以拥有任何一项活动,但前提是该用户所属的组与该活动有关系。

HasOneThrough doesn't seem to work here, since the group the user is related through has multiple activities. HasOneThrough 似乎在这里不起作用,因为与用户相关的组有多个活动。 HasManyThrough doesn't work since the user can only have one. HasManyThrough 不起作用,因为用户只能拥有一个。

I want to properly model this relationship so that it can be picked up for selection automatically via a Nova relationship field, but I'm struggling to figure out exactly how I would do so.我想正确地 model 这种关系,以便可以通过 Nova 关系字段自动选择它,但我正在努力弄清楚我将如何做到这一点。 My first thought is a HasOneThrough relation with some set of subqueries, but I can't quite piece together where to start.我的第一个想法是与一组子查询的 HasOneThrough 关系,但我不能完全拼凑出从哪里开始。

How would I do this, or conversely, is it possible via Eloquent's automatic relationship system at all?我将如何做到这一点,或者相反,是否可以通过 Eloquent 的自动关系系统来实现?

To ensure we are on the same idea of your relationships:为了确保我们对您的关系有相同的想法:

The relationship between Groups and Activities is a Many To Many relationship ( Many To Many - Larvel Documentation ).组和活动之间的关系是多对多关系( 多对多 - Larvel 文档)。

The group_activities table is the pivot table. group_activities表是 pivot 表。

The relationship between users and groups is a One To Many relationshipOne To Many - Larvel Documentation and the inverse of it One To Many (Inverse) - Larvel Documentation .用户和组之间的关系是一对多关系One To Many - Larvel Documentation和它的逆One To Many (Inverse) - Larvel Documentation

To actually answer your question:要实际回答您的问题:

If you want to use a shortcut from users to their activities, the Has Many Through is the correct way.如果您想使用从用户到他们的活动的快捷方式,Has Many Through 是正确的方法。 If a group can have arbitrary many activities, and a user belongs to one group, the user will be associated to these arbitrary many activities through the group -hence Has Many Through.如果一个组可以有任意多个活动,并且一个用户属于一个组,则该用户将通过该组与这些任意多个活动相关联-因此具有许多通过。 Note that this is not really a separate relationship though, it's just a convient shortcut.请注意,这并不是真正的单独关系,它只是一个方便的快捷方式。

If you wan't to associate a user with a single Activity directly, you need to to this via a separate One to Many relationship between Users and Activities.如果您不想直接将用户与单个活动相关联,则需要通过用户和活动之间单独的一对多关系来实现。

I'm not entirely sure if I interpret your question correctly, so the following is just an assumption, but do you want to ensure a user can only be associated to an activity thats also associated with the user group?我不完全确定我是否正确解释了您的问题,因此以下只是一个假设,但您是否要确保用户只能与也与用户组相关联的活动相关联? So to restrict possible activites by group?所以要按组限制可能的活动? If that is the case, you'd simply need to check if the selected activity is in the activities associated with the users group:如果是这种情况,您只需检查所选活动是否在与用户组关联的活动中:

With your relationships set up like this:像这样建立您的关系:

class User {

    public function activity(){
        return $this->belongsTo('App\Activity');
    }

    public function possibleActivities(){
         return $this->hasManyThrough('App\Activity','App\Group');
    }
}

you can check and associate activities like this:您可以像这样检查和关联活动:

if( $user->possibleActivities()->contains( $activity ) ){
    $user->activity()->associate($activity);
}

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

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