【问题标题】:Laravel eloquent where filter HasMany relationship not working as desiredLaravel 雄辩,其中过滤器 HasMany 关系无法按预期工作
【发布时间】:2020-06-25 03:21:32
【问题描述】:

我知道有些人会说这是一个重复的问题。 等等,我有一个特殊的情况,到目前为止我在任何其他帖子上都没有发现。

我有一个用户模型 (User.php) 和一个团队模型 (Team.php)。

用户属于一个团队。一个团队有很多用户。

在用户模型中,我有这个属性(列)“类型”。

从团队模型中,我想在数据表中显示所有团队的列表,其中包含类型为“初学者”的用户。

User.php

protected $with = ['team'];

public function team(){
    return $this->belongsTo(Team::class);
}

Team.php

public function members(){
    return $this->hasMany(User::class)->where('users.type','=','beginner');
}

如您所见,我已经在过滤要显示的用户了。

假设我有以下数据:

团队

Team one: User 1 (type: intermediate), User 2 (type: intermediate)
Team two: User 3 (type: beginner), User 4 (type: beginner)
Team three: User 5 (type: beginner), User 6 (type: beginner)

但是,当我获得团队列表时,所有团队都会显示出来,这是我不想要的。

|     Team    |      Members    |
--------------------------------|
|  Team one   |                 |
|  Team two   |  User 3, User 4 |
|  Team three |  User 5, User 6 |
---------------------------------

在这种情况下,我想要的是不显示“Team one”。这部分有效,因为没有为第一组显示任何成员。

我第一次尝试:

$teams = Team::with('members')->get();

然后是这个:

$teams = Team::with(['members'=>function($query){
                $query->where('users.type','beginner');
            }])->get();

但它不会过滤掉不受欢迎的团队。

关于如何实现这一点的任何想法?

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    首先 with 的 eloquent 函数看起来像 MYSQL 上的 LEFT JOIN,所以如果你只想要有初学者用户的团队,只需使用 haswhereHas 函数

    $teams = Team::has('members')->get();
    

    【讨论】:

      【解决方案2】:

      我总是建议建立没有“wheres”的关系,这样你就可以从不同的地方重复使用它来满足各种需求......

      public function members(){
          return $this->hasMany(User::class);
      }
      

      那么,要获得有成员的团队,只有那些获得“初学者”你的团队 使用 whereHas

      $teams = Team::whereHas('members',function($query){
              $query->where('users.type','beginner');
          })->with('members') ->get();
      

      【讨论】:

      • with 是不必要的
      • 欢迎@H.Rafiee,问题是:我想在数据表中显示所有团队及其用户的列表,我再次引用(与他们的用户)
      • 但他说“在这种情况下,我想要的是不显示‘Team one’。”所以当haswhereHas 就足够了
      【解决方案3】:

      你可以运行:

      Team::has('members')->with('members')->get();
      

      还有一种解决方法可以在不使用 where 子句的情况下对关系设置过滤器。

      Team.php

      class Team extends Model
      {
          public function users(){
              return $this->hasMany(User::class);
          }
      
          public function members(){
              return $this->hasMany(Member::class);
          }
      }
      

      接下来,我们将创建模型“Member”作为 User 的子类。

      会员.php

      class Member extends User
      {
          protected static $type = 'beginner';
      }
      

      最后我们将以下代码(*)添加到用户(只显示添加的代码,而不是整个类)。

      (*) 使用Late Static Bindings

      table 属性必须设置为“users”,以便 Member 模型也使用“users”表而不是“members”表。

      User.php

      class User extends Authenticatable
      {
          protected $table = 'users';
      
          protected static $type = null;
      
          public function team()
          {
              return $this->belongsTo(Team::class);
          }
      
          /**
           * The "booting" method of the model.
           *
           * @return void
           */
          protected static function boot()
          {
              parent::boot();
      
              static::saving(function ($model) {
                  $model->type = static::$type ?? $model->type;
              });
      
              static::addGlobalScope('Type', function ($query) {
                  return static::$type ? $query->where('type', static::$type) : $query;
              });
          }
      }
      

      另外,通过Member模型更容易创建初学者用户。

      Member::create(['name' => 'Iggy Pop', 'email' => 'rock@iguana.com']);
      

      由于默认情况下类型设置为“初学者”,这要归功于:

      static::saving(function ($model) {
          $model->type = static::$type ?? $model->type;
      });
      

      (保存方法在Member的每个insert和update事件上执行)。

      同理,Member::all() 按“初学者”类型过滤用户,原因是:

      static::addGlobalScope('Type', function ($query) {
          return static::$type ? $query->where('type', static::$type) : $query;
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-28
        • 1970-01-01
        • 2018-10-18
        • 2018-03-05
        • 1970-01-01
        相关资源
        最近更新 更多