Подтвердить что ты не робот

Вложенные отношения Laravel

У меня много проблем с установлением очень вложенных отношений для правильной работы в Laravel.

Разыскиваемое поведение заключается в следующем,

Я выбираю событие по идентификатору и хочу посмотреть, какие лица подписаны на него. Теперь проблема в том, что между событием и человеком есть несколько таблиц.

Это запрос, который работает!

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 так сложно добиться такого рода вложенных отношений?

Спасибо!

4b9b3361

Ответ 1

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

Если вы хотите только выбрать определенные поля из таблицы persons, используйте это:

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

Ответ 2

Для конкретных городов и компаний необходимо распределить их с красноречивым. Например:

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

Ответ 3

Я создал отношение HasManyThrough для таких случаев: Репозиторий на 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', '...']);
}

Ответ 4

Чтобы расширить @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 в основном домене, после всего этого без присмотра.