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!
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();
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();
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', '...']);
}