【问题标题】:Laravel - Eloquent relation whereHas one or more other relationsLaravel - 有一个或多个其他关系的雄辩关系
【发布时间】:2019-06-18 05:33:56
【问题描述】:

我现在正在学习 Laravel 和 Laravel eloquent,现在我尝试使用 Laravel 中的关系来解决问题。 这是我要归档的内容:

该数据库包含许多体育俱乐部。体育俱乐部有很多球队。每支球队都有比赛。团队表有一个名为 club_id 的列。现在我想创建 Eloquent 关系来获取俱乐部的所有游戏。

这是我目前得到的:

俱乐部模式

id => PRIMARY

public function games()
    {
        return $this->hasMany('App\Models\Games')->whereHas('homeTeam')->orWhereHas('guestTeam');
    }

游戏模型

home_id => FOREIGN KEY of team ; guest_id => FOREIGN KEY of team

public function homeTeam()
    {
        return $this->belongsTo('App\Models\Team','home_id')->where('club_id','=', $club_id);
    }

    public function guestTeam()
    {
        return $this->belongsTo('App\Models\Team','guest_id')->where('club_id','=', $club_id);
    }

团队模型

id => PRIMARY ; club_id => FOREIGN

在我的控制器中,我只想Club::findOrFail($id)->games()

执行上面的代码会返回一个 SQL 错误,即游戏表没有名为 club_id 的列。

创建这种关系的正确方法是什么?

谢谢!

编辑

感谢 Nikola Gavric,我找到了获得所有比赛的方法 - 但仅限于俱乐部球队是主队或客队的情况。

关系如下:

public function games()
    {
        return $this->hasManyThrough('App\Models\Game','App\Models\Team','club_id','home_id');
    }

如何获得 home_id 或 guest_id 与俱乐部球队匹配的比赛?此函数中的最后一个参数不允许使用数组。

【问题讨论】:

    标签: laravel eloquent eloquent-relationship


    【解决方案1】:

    有一种方法可以检索“与中介的远距离关系”,称为Has Many Through

    还有一个关于如何使用它的具体示例,包括PostCountryUser,但我认为给你一个关于如何在内部创建games 关系的提示就足够了Club 模型。 Here 是一个链接,但是当你打开它时,搜索 hasManyThrough 关键字,你会看到一个例子。

    P.S:使用正确的keys naming,您可以通过以下方式实现它:

    public function games()
    {
        return $this->hasManyThrough('App\Models\Games', 'App\Models\Teams');
    }
    

    编辑#01

    由于您有 2 种类型的团队,因此您可以创建 2 种不同的关系,其中每种关系都会为您提供所需的一种类型。像这样:

    public function gamesAsHome()
    {
        return $this
            ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'home_id');
    }
    
    public function gamesAsGuests()
    {
        return $this
            ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'guest_id');
    }
    

    编辑#02

    合并关系:要合并这两个关系,您可以在Collection 实例上使用merge() 方法,它会做的是,它将追加所有记录从第二个集合第一个

    $gamesHome = $model->gamesAsHome;
    $gamesGuests = $model->gamesAsGuests;
    $games = $gamesHome->merge($gamesGuests);
    
    return $games->unique()->all();
    

    感谢@HCK 指出合并后您可能有重复,并且需要unique() 才能在合并后获得独特的游戏


    编辑#03

    sortByCollection 包含numerical indexing 的情况下还提供callable 而不是attribute name。您可以像这样对Collection 进行排序:

    $merged->sortBy(function($game, $key) {
        return $game->created_at;
    });
    

    【讨论】:

    • 我几乎明白了!我现在在这里使用这个:return $this->hasManyThrough('App\Models\Games', 'App\Models\Teams','id','home_id'); ... 有了这个,我得到了俱乐部的所有主场比赛。但是我怎样才能添加or,这样我才能获得俱乐部球队是主队或客队的所有比赛
    • 您可以在与filter 的关系上进一步使用where
    • ...->games() 仅返回 home_id 是俱乐部的 team_id 的游戏。当我删除最后两个参数(如您的示例)时,我得到一个 SQL 异常。我无法向hasManyThrough 函数的secondKey 参数添加数组(例如['home_id','guest_id']
    • SortBy 还提供了一个 callable 而不是 attribute name 来排序。我现在会用一个例子来更新我的答案
    • 很高兴你解决了它,希望你学到了一点:) 不客气
    【解决方案2】:

    当您定义 Club hasMany 游戏时,您表示该游戏有一个名为 club_id 的外键指向 Club。 belongsTo 是相同的,但方式不同。这些需要与您的数据库中的内容保持一致,这意味着您需要将这些键定义为表上的外键。

    【讨论】:

    • 比赛桌只有主场和客队作为外键,指向球队。团队有一个名为 club_id 的外键,它指向俱乐部
    • 当你在 Club 类的游戏函数上说 $this->hasMany('App\Models\Games') 时,你表示 Game 有一个 club_id,这就是为什么“一个俱乐部有很多游戏”。
    【解决方案3】:

    试试这个...

    俱乐部模式

    public function games()
        {
            return $this->hasMany('App\Models\Games');
        }
    

    游戏模型

    public function homeTeam()
        {
            return $this->belongsTo('App\Models\Team','home_id');
        }
    
        public function guestTeam()
        {
            return $this->belongsTo('App\Models\Team','guest_id');
        }
    

    您的查询喜欢

    Club::where('id',$id)->has('games.guestTeam')->get();
    

    【讨论】:

      猜你喜欢
      • 2017-10-17
      • 2012-10-08
      • 2020-04-10
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多