Получите фильтрацию моделей Laravel по отношениям «многие ко многим»

У меня есть схема базы данных фильмов (только данные, относящиеся к вопросу):

persons (yes, I used "persons" instead of "people"...)
id
name

roles
id
name

roles_persons
person_id
role_id

И соответствующие модели, определяющие отношения «многие ко многим»:

class Person extends Model
{
    protected $table = 'persons';

    public function roles(){
        return $this->belongsToMany('App\Role', 'roles_persons')->withTimestamps();
    }
}

class Role extends Model
{
    public function persons(){
        return $this->belongsToMany('App\Person', 'roles_persons')->withTimestamps();
    }
}

Пока все в порядке.

Одна из ролей - "директор".

Теперь я хочу добавить таблицу «фильмы», у которой есть внешний ключ с идентификатором директора (человека с ролью «режиссер»).

films
id
title
director_person_id

В методе создания FilmsController я пытаюсь отправить на просмотр список с режиссерами (чтобы отобразить выбор ввода для выбора одного).

Как правильно это сделать?

class FilmsController extends Controller
{
    public function create()
    {
        $directorRole = Role::find('1');

        $directorsToChoose = Person::  ???

        return view('films.create')->with('directors', $directors);
    }
}

Я видел связанный с этим вопрос, но не понимаю, как его применить в данном случае.

Спасибо.


person nanocv    schedule 14.10.2018    source источник


Ответы (1)


Не рекомендуется использовать ключи сводной таблицы в качестве внешних ключей для другой таблицы. В таких сценариях вы можете добавить первичный ключ в таблицу и использовать этот ключ в качестве внешнего ключа.

person_roles
id (первичный ключ)
role_id
person_id

фильмы
id
person_role_id (внешний ключ)

Поскольку это не сводная таблица, создайте также модель Eloquent.

PersonRole

class PersonRole extends Model
{
    protected $table = 'persons_roles';

    public function role()
    {
        return $this->belongsTo(Role::class);
    }

    public function person()
    {
        return $this->belongsTo(Person::class);
    }
}

Человек

class Person extends Model
{
    protected $table = 'persons';

    public function personRole
    {
        return $this->hasMany(PersonRole::class);
    }
}

Роль

class Person extends Model
{
    protected $table = 'roles';

    public function personRole
    {
        return $this->hasMany(PersonRole::class);
    }
}

Затем отправьте идентификаторы этих таблиц в форму создания фильмов для выбора.

class FilmsController extends Controller
{
    public function create()
    {
        $directors = PersonRole::whereHas('role', function ($roles) {
            $roles->where('name', 'director');
        })
        ->with('person')
        ->get();

        return view('films.create')->with('directors', $directors);
    }
}

Просмотреть

<select>
    @foreach($directors as $director)
        <option value="{{ $director->id }}">{{ $director->person->name }}</option>
    @endforeach
</select>
person Tharaka Dilshan    schedule 14.10.2018
comment
Спасибо за разработку длинного ответа. Я очень ценю полезные советы. Итак, пытаясь хорошо понять, всегда ли рекомендуется разбивать все отношения «многие ко многим» на два отношения «один ко многим» (и создавать модель для этой промежуточной таблицы)? Или только тогда, когда ключ сводной таблицы будет использоваться в качестве внешнего ключа в другой таблице? - person nanocv; 14.10.2018
comment
только когда ключ сводной таблицы будет использоваться в качестве внешнего ключа в другой таблице - person Tharaka Dilshan; 14.10.2018