Laravel嵌套关系

时间:2014-09-02 17:08:53

标签: php mysql database laravel

我有很多很多很难让一个非常嵌套的关系在laravel中正常工作。

想要的行为如下,

我按ID选择一个活动,我想知道哪些人订阅了它。 现在问题是事件和人之间有一些表格。

这是有效的查询!

SELECT persons.id, 
       persons.firstname, 
       persons.lastname, 
       event_scores.score 
FROM   events 
       JOIN cities 
         ON cities.id = events.city_id 
       JOIN companies 
         ON cities.id = companies.city_id 
       JOIN persons 
         ON companies.id = persons.company_id 
       JOIN event_scores 
         ON event_scores.person_id = persons.id 
WHERE  event_scores.event_id = 1 
GROUP  BY persons.id 

这些是我的关系

活动模型

class Event extends Eloquent
{
    protected $table = 'events';

    public function city()
    {
        return $this->belongsTo('City');
    }
}

城市模型

class City extends Eloquent
{
    protected $table = 'cities';

    public function companies()
    {
        return $this->hasMany('Company');
    }

    public function event()
    {
        return $this->hasMany('Event');
    }
}

公司模式

class Company extends Eloquent {

    protected $table = 'companies';

    public function persons()
    {
        return $this->hasMany('Person');
    }

    public function city()
    {
        return $this->belongsTo('City');
    }
}

人物模型

class Person extends Eloquent
{
    protected $table = 'persons';

    public function company()
    {
        return $this->belongsTo('Company');
    }

    public function eventscore()
    {
        return $this->belongsToMany('Event', 'event_scores', 'person_id', 'event_id')
            ->withPivot('score')
            ->withTimestamps();
    }
}

我尝试了什么

return Event::with('city')->with('company')->get();

return Event::with('city')
    ->whereHas('companies', function($query) use ($company_id){
        $query->where('company_id', $company_id);
    })->get();

还有很多其他的可能性,我真的坚持这个。在laravel中实现这种嵌套关系链接是否如此困难?

谢谢!

5 个答案:

答案 0 :(得分:73)

return Event::with('city.companies.persons')->get();

如果您只想从persons表中选择某些字段,请使用:

return Event::with(['city.companies.persons' => function ($query) {
    $query->select('id', '...');
}])->get();

答案 1 :(得分:15)

对于城市和公司特定领域,您需要分发具有说服力的人。 例如:

return Event::with([
    'city' => function ($query) {
        $query->select('id', '...');
    },
    'city.companies' => function ($query) {
        $query->select('id', '...');
    },
    'city.companies.persons' => function ($query) {
        $query->select('id', '...');
    }
])->get();

答案 2 :(得分:1)

我为以下情况创建了HasManyThrough关系:Repository on GitHub

安装后,您可以像这样使用它:

class Event extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function persons() {
        return $this->hasManyDeep(
            Person::class,
            [City::class, Company::class],
            ['id'],
            ['city_id']
        );
    }
}

您可以使用withIntermediate()从中间表中获取属性:

public function persons() {
    return $this->hasManyDeep(
        Person::class,
        [City::class, Company::class],
        ['id'],
        ['city_id']
    )->withIntermediate(City::class, ['id', '...']);
}

答案 3 :(得分:0)

扩展@ rashmi-nalwaya的答案。我通过一些调整将其用于5.8项目。

我的示例有些不同,因为我试图引用hasOne关系,而不是hasMany。

因此,作为参考,域属于一个网站,而该网站属于一台服务器。我只想从所有这些表中返回某些列。我必须这样做。

Domain::with([
    'website' => function($q){
        $q->select('id', 'server_id');
    },
    'website.server' => function($q){
        $q->select('id', 'hostname', 'nickname');
    }
])
    ->select('id', 'website_id', 'domain')
    ->get();

必须确保我可以随时通过我所使用的表的主键(因此,我的情况是id),其次,我要尝试的相关表的外键到达,得到。因此,website_id来自域,server_id来自网站。然后效果很好。

在我的代码中,除此以外,在主域上还有一个where子句。

答案 4 :(得分:0)

return Event::with(['city:id,name', 'city.companies:id,name', 'city.companies.persons:id,name'])->get();