Отношение HasMany через отношение BelongsToMany - PullRequest
0 голосов
/ 14 мая 2019

Возможно ли установить отношение Laravel через отношения ownToMany?

У меня есть 4 таблицы:

1) Restaurants (id, name) - использует hasManyRelation с таблицей Workers

2) Директора (идентификатор, имя)

3) Директора_Рестораны (идентификатор, директор_ид, restaurant_id) - сводная таблица для подключения к множеству ресторанов с директорами

3) Рабочие (идентификатор, имя, restaurant_id)

С помощью этой функции в модели Director я могу получить все подключенные рестораны

public function restaurants()
{
    return $this->belongsToMany('App\Restaurant','director_restaurant');
}

С помощью этой функции в моем коде я могу получить всех работников всех ресторанов одного директора

$director = Director::find(1);
$director->load('restaurants.workers');
$workers = $director->restaurants->pluck('workers')->collapse();

Итак, мой вопрос: могу ли я объявить подобное отношение в моей модели Director, чтобы получить всех своих работников во всех его ресторанах?

Ответы [ 4 ]

2 голосов
/ 14 мая 2019

Конечно, вы можете использовать hasMany метод отношений для модели Director с Eager Loading

как показано ниже

public function restaurants()
{
    return $this->hasMany(Restaurant::class)->with('restaurants.workers');
}
1 голос
/ 14 мая 2019

Вы можете определить метод accessor в своей модели, чтобы скрыть некоторую логику

# App/Director.php

// You'll need this line if you want this attribute to appear when you call toArray() or toJson()
// If not, you can comment it
protected $appends = ['workers'];

public function getWorkersAttribute()
{
    return $this->restaurants->pluck('workers')->collapse();
}

# Somewhere else
$director = Director::with('restaurants.workers')->find(1);
$workers = $director->workers;

Но в конечном итоге вам все равно придется загрузить вложенное отношение 'restaurants.workers', чтобы оно заработало.

Учитывая атрибуты вашей таблицы, вы также можете определить пользовательские отношения HasMany, которые выглядят так:

# App/DirectorRestaurant.php

public function workers()
{
    return $this->hasMany(Worker::class, 'restaurant_id', 'restaurant_id');
}

# Somewhere else
$director = Director::find(1);
$workers = DirectorRestaurant::where('director_id', $director->id)->get()->each(function($q) { $q->load('workers'); });

Но я не рекомендую это, потому что они не очень читабельны.

Наконец, есть пакет staudenmeir/eloquent-has-many-deep, в котором вы можете определить такого рода вложенные отношения.

https://github.com/staudenmeir/eloquent-has-many-deep

1 голос
/ 14 мая 2019

Вы можете определить прямую связь, "пропустив" таблицу restaurants:

class Director extends Model
{
    public function workers()
    {
        return $this->belongsToMany(
            Worker::class,
            'director_restaurant',
            'director_id', 'restaurant_id', null, 'restaurant_id'
        );
    }
}
1 голос
/ 14 мая 2019

Я могу предложить решение, подобное этому:

Модель Директора ВАРИАНТ 1

public function getAllRestaurants(){
    return $this->hasMany(Restaurant::class)->with('restaurants.workers');
}

Модель Директора ВАРИАНТ 2

public function getAllRestaurants(){
    $this->load('restaurants.workers');
    return $this->restaurants->pluck('workers')->collapse();
}

Вы можете найти все рестораны в любом месте

$all_restaurants = Director::find(1)->getAllRestaurants();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...