php Laravel 嵌套关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25628754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 17:55:29  来源:igfitidea点击:

Laravel nested relationships

phpmysqldatabaselaravel

提问by Miguel Stevens

I'm having trouble getting a very-nested relationship to work correctly in laravel.

我无法在 laravel 中建立一个非常嵌套的关系才能正常工作。

The wanted behaviour is as follows,

想要的行为如下,

I select an event by ID and i want to see which persons are subscribed to it.Now the problem is there are some tables between the event and the person..

我通过 ID 选择一个事件,我想查看哪些人订阅了它。现在的问题是事件和人之间有一些表格。

This is the query that works!

这是有效的查询!

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 

These are my relations

这些是我的关系

Event Model

事件模型

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

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

City Model

城市模型

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

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

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

Company Model

公司模式

class Company extends Eloquent {

    protected $table = 'companies';

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

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

Person Model

人物模型

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();
    }
}

What I have tried

我试过的

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

and

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

And many other possibilities, I'm really stuck on this. Is it so difficult in laravel to achieve this kind of nested relationship linking?

还有许多其他的可能性,我真的坚持这一点。在laravel中实现这种嵌套关系链接有那么难吗?

Thanks!

谢谢!

回答by Joseph Silber

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

If you only want to select certain fields from the personstable, use this:

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

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

回答by Rashmi Nalwaya

For city and companies specific fields , you need to distribute the with eloquent. Eg:

对于城市和公司特定的领域,你需要用 eloquent 分发。例如:

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();

回答by Jonas Staudenmeir

I created a HasManyThroughrelationship for cases like this: Repository on GitHub

HasManyThrough为这样的案例创建了一个关系:GitHub 上的存储库

After the installation, you can use it like this:

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

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

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

You can get attributes from intermediate tables with withIntermediate():

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

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

回答by John Halsey

To expand on @rashmi-nalwaya 's answer. I got it working for a 5.8 project with some tweaks.

扩展@rashmi-nalwaya 的答案。我通过一些调整让它在 5.8 项目中工作。

My example was a bit different because I am trying to reference hasOne relations, rather than hasMany.

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

So for reference, Domains belong to one Website, which belongs to one Server. I only wanted to return certain columns from all of those tables. I had to do this.

所以作为参考,域名属于一个网站,属于一个服务器。我只想从所有这些表中返回某些列。我不得不这样做。

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();

Had to make sure I passed through the primary key for the table I'm on at any time (so the idin my case), and secondly, the foreign key of the related table I'm trying to get to. So website_idfrom domain, and server_idfrom website. Then it worked perfectly.

必须确保我随时通过我所在的表的主键(id在我的情况下是这样),其次,我试图访问的相关表的外键。因此,website_id来自域和server_id网站。然后它完美地工作。

In my code I also have a further where clause on the main domain, after all this with-ness.

在我的代码中,我在主域上还有一个进一步的 where 子句,毕竟这一切都是如此。