wake-up-neo.com

Laravel verschachtelte Beziehungen

Ich habe eine Menge Probleme, eine sehr verschachtelte Beziehung zu bekommen, um in Laravel richtig zu arbeiten.

Das gewünschte Verhalten ist wie folgt: 

Ich wähle ein Ereignis nach ID aus und möchte sehen, welche Personen es abonniert haben. Nun besteht das Problem darin, dass zwischen dem Ereignis und der Person einige Tabellen liegen.

Dies ist die Abfrage, die funktioniert!

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 

Das sind meine Beziehungen

Ereignismodell

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

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

Stadtmodell

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

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

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

Unternehmensmodell

class Company extends Eloquent {

    protected $table = 'companies';

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

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

Personenmodell

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

Was ich versucht habe

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

und

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

Und viele andere Möglichkeiten, ich bin wirklich fest damit beschäftigt. Ist es in Laravel so schwierig, diese Art von verschachtelten Beziehungsverknüpfungen zu erreichen?

Vielen Dank!

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

Wenn Sie nur bestimmte Felder aus der Tabelle persons auswählen möchten, verwenden Sie Folgendes:

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

Für stadt- und firmenspezifische Felder müssen Sie die mit eloquent .. .. verteilen. 

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();
14
Rashmi Nalwaya

Ich habe eine HasManyThrough-Beziehung für folgende Fälle erstellt: Repository auf GitHub

Nach der Installation können Sie es folgendermaßen verwenden:

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

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

Sie können Attribute aus Zwischentabellen mit withIntermediate() erhalten:

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

Um die Antwort von @ rashmi-nalwaya zu erweitern. Ich habe es für ein 5.8-Projekt mit ein paar Verbesserungen zum Laufen gebracht.

Mein Beispiel war ein bisschen anders, weil ich versuche, mich auf hasOne-Beziehungen zu beziehen, anstatt auf hasMany.

Als Referenz gehören Domains zu einer Website, die zu einem Server gehört. Ich wollte nur bestimmte Spalten aus all diesen Tabellen zurückgeben. Ich musste das machen.

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

Ich musste sicherstellen, dass ich den Primärschlüssel für die Tabelle, auf der ich mich gerade befinde, durchlief (also in meinem Fall den id), und zweitens den Fremdschlüssel für die verknüpfte Tabelle, die ich abrufen möchte zu. Damit website_id von Domain und server_id von der Website. Dann hat es perfekt geklappt.

In meinem Code habe ich auch eine weitere where-Klausel für die Hauptdomäne, nach all dem ohne Erfolg.

0
John Halsey