【问题标题】:Check whether many-to-many relationship exists Laravel检查 Laravel 是否存在多对多关系
【发布时间】:2013-11-19 12:11:17
【问题描述】:

我有以下型号:

/* Team.php */

class Team extends Eloquent {

  public function users() {
    return $this->belongsToMany('User');
  }

}

/* User.php */

class User extends Eloquent {

  public function teams() {
    return $this->hasMany('Team');
  }

}

和数据库结构:

teams
  id
  user_id
  name

users
  id
  email

team_user
  id
  team_id
  user_id

用户可以创建(并拥有 - 因此是 teams.user_id)一个团队,但也属于其他团队。

如果可能,我希望能够使用 Eloquent 为特定用户获取所有团队,而无需像这样执行自定义 SQL 查询:

 SELECT teams.* 
 FROM teams 
 JOIN team_user 
 ON (team_user.team_id = teams.id) 
 WHERE team_user.user_id = ?

自定义 SQL 查询有效,但我确信这不是 Laravel 的原生方式。

有人可以帮忙吗?提前感谢您的阅读。

【问题讨论】:

    标签: laravel laravel-4 eloquent


    【解决方案1】:

    为了回答标题中的问题,以下是您如何在用户模型中定义布尔函数以了解数据透视表“team_user”中是否存在关系:

    public function isPartOfThe($team)
    {
        return $this->teams()->where('team_id', $team->id)->exists();
    }
    

    然后你可以在你的控制器中调用函数如下:

    If($user->isPartOfThe($team)
    {
        //true
    }
    

    【讨论】:

    • 太棒了!我喜欢这个解决方案,因为我认为它对数据库更友好。而不是选择所有记录并遍历。
    【解决方案2】:

    您应该在关系的两边都返回$this-belongsToMany(Model::class),以便使用您的数据透视表。

    /* Team.php */
    
    class Team extends Eloquent {
    
        public function users() {
            return $this->belongsToMany(User::class);
        }
    
    }
    
    /* User.php */
    
    class User extends Eloquent {
    
        public function teams() {
            return $this->belongsToMany(Team::class);
        }
    
    }
    

    团队中不需要有user_id 字段,因为这隐含地表示Many-to-one。 (这个团队只有一个用户)

    解决此问题后,使用 eloquent 为用户获取所有团队将非常简单:

    User::teams()->get();
    

    反之

    Team::users()->get();
    

    或者获取一个包含所有团队的用户实体:

    User::with('teams')->get();
    

    反之亦然

    Team::with('users')->get();
    

    【讨论】:

    • 安东尼奥、乔希和你自己都是正确的——需要belongsToMany关系。认为我需要弄清楚这将对应用程序的其余部分产生什么影响,因为团队现在没有所有者用户(这就是为什么一开始就没有反向关系的原因。
    • 如果您使用它来确定该对象的所有权,则没有理由删除团队中的 user_id 列。话虽如此,将密钥命名为 owner_id 或类似名称更合适。
    • @Abba 是的,这是真的,当然是 OP 在 cmets 中所说的。事实上,没有理由不能与多对多并行创建特定的多对一关系。
    【解决方案3】:

    在我看来你快到了,你已经设置好了关系,所以现在你只需要:

    $user = User::find(1);
    
    foreach($user->teams as $team)
    {
       echo $team->name;
    }
    

    由于 Laravel 需要一个 teams_users 数据透视表名称,您可能还需要告诉它正确的名称并在两者上都使用 belongsToMany():

    class Team extends Eloquent {
    
      public function users() {
        return $this->belongsToMany('User', 'team_user');
      }
    
    }
    
    class User extends Eloquent {
    
      public function teams() {
        return $this->belongsToMany('Team', 'team_user');
      }
    
    }
    

    【讨论】:

      【解决方案4】:

      应该是这样的

      class User {
          public function teams() {
              return $this->belongsToMany('User', 'team_user');
          }
      }
      
      
      class Team {
          public function user() {
              return $this->belongsToMany('Team', 'team_user');
          }
      }
      

      【讨论】:

        【解决方案5】:

        如果您使用它来确定该对象的所有权,则没有理由删除团队中的 user_id 列。

        话虽如此,将密钥更恰当地命名为 manager_id 或类似名称会更有意义。此外,没有任何迹象表明您必须使用与相关(复数)表名称相同的关系函数名称。

        除了上面的 belongsToMany 设置之外,试试这样的方法:

        <?php
            class Team extends Eloquent {
        
                ...
        
                public function manager()
                {
                    return belongsTo('User', 'manager_id');
                }
        
                ...
        
            }
        
        <?php
            class User extends Eloquent {
        
                ...
        
                public function manages()
                {
                    return hasMany('Team', 'manager_id');
                }
        
                ...
        
            }        
        

        我不觉得之前的答案完全解释了您尝试的数据模型。

        【讨论】:

          猜你喜欢
          • 2014-05-28
          • 1970-01-01
          • 2022-01-12
          • 2020-06-21
          • 1970-01-01
          • 1970-01-01
          • 2014-08-24
          • 2021-08-29
          • 1970-01-01
          相关资源
          最近更新 更多