如何在Eraquent模型中为Laravel中的三个表定义一对多以及多对多关系?

时间:2018-01-05 11:42:58

标签: laravel eloquent laravel-5.5

我有三张桌子:

  • 项目
  • 版本
  • 补丁

关系是:

  • 项目 - >版本(一对多)
  • 版本< - >补丁(多对多)

参见简化模型:

enter image description here

我需要显示项目的所有补丁。我可以这样做:

@foreach( $project->versions as $version)
    @foreach( $version->patches as $patch)
            {{ $patch->something }}
    @endforeach
@endforeach

但当然它会显示多个适用于多个版本的补丁。

如何在模型中定义此关系并删除重复的修补程序?我寻找像这样的东西(model \ App \ Project):

public function patches()
{
    return $this->hasManyThrough(
        'App\Patch',
        'App\Version',
        'projects_id',
        '???',
        'id'
    )->groupBy('patches.id');
}

我的模型中有以下方法:

项目

public function versions()
{
    return $this->hasMany('App\Version', 'projects_id');
}

版本

public function project()
{
    return $this->belongsTo('App\Project', 'projects_id');
}

public function patches()
{
    return $this->belongsToMany('App\Patch', 'versions_patches', 'versions_id', 'patches_id');
}

修补程序

public function versions()
{
    return $this->belongsToMany('App\Version', 'versions_patches', 'patches_id', 'versions_id');
}

2 个答案:

答案 0 :(得分:2)

在您的项目模型中:

public function versions()
{
    return $this->hasMany('App\Version');
}

在您的版本模型中:

public function versions()
{
    return $this->hasMany('App\Patch');
}
修补程序模型中的

public function versions()
{
    return $this->belongsToMany('App\Patch');
}

显示项目的所有pacthes:(您的代码是正确的!)

@foreach( $projects->versions as $version)
    @foreach( $version->patches as $patch)
            {{ $patch->something }}
    @endforeach
@endforeach

但上面的代码会产生N + 1问题,因此您需要事先加载关系

$projects = App\Project::with('versions.patches')->get();

答案 1 :(得分:1)

Patch.php:

public function versions()
{
    return $this->belongsToMany('App\Version','versions_patches','patches_id','versions_id');
}

版本型号:

public function projects()
{
    return $this->hasMany('App\Project');
}

然后......

$projectPatches = $patches->whereHas('versions_id', function($q) use ($project) {
    return $q->where('projects_id',$project->version);
})->get();