Relations imbriquées Laravel

J'ai beaucoup de mal à obtenir une relation très imbriquée pour fonctionner correctement dans laravel.

Le comportement recherché est le suivant,

Je sélectionne un événement par ID et je veux voir quelles personnes y sont abonnés. Maintenant, le problème est qu'il y a quelques tables entre l'événement et la personne..

C'est la requête qui fonctionne!

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 

Ce sont mes relations

Modèle D'Événement

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

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

Ville Modèle

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

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

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

Modèle D'Entreprise

class Company extends Eloquent {

    protected $table = 'companies';

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

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

Modèle De Personne

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

Ce que j'ai essayé

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

Et

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

Et bien d'autres possibilités, je suis vraiment coincé là-dessus. Est-il si difficile à laravel de réaliser ce genre de relation imbriquée?

Merci!

26
demandé sur Habib Qadoos 2014-09-02 21:08:52

3 réponses

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

Si vous ne souhaitez sélectionner que certains champs de la table persons, Utilisez ceci:

return Event::with(['city.companies.persons' => function ($query) {
    $query->select('id', '...');
}])->get();
61
répondu Joseph Silber 2015-11-05 20:01:02

Pour les champs spécifiques à la ville et aux entreprises, vous devez distribuer le avec eloquent. Par exemple:

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();
13
répondu Rashmi Nalwaya 2016-09-21 08:07:42

J'ai créé une relation HasManyThrough pour des cas comme celui-ci: Repository sur GitHub

Après l'installation, vous pouvez l'utiliser comme ceci:

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

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

Vous pouvez obtenir des attributs à partir de tables intermédiaires avec withIntermediate():

public function persons() {
    return $this->hasManyDeep(
        Person::class,
        [City::class, Company::class],
        ['id'],
        ['city_id']
    )->withIntermediate(City::class, ['id', '...']);
}
0
répondu Jonas Staudenmeir 2018-09-26 19:15:37