Laravel ›Использование Eloquent Запрос отношений" многие-ко-многим "

Я пытаюсь понять, как работает Eloquent и какие преимущества перед использованием простых запросов sql (объедините таблицы A и B в columA.id = columnB.id ...)

У меня есть две модели: каналы и подкатегории в отношении "многие ко многим".

Я создал сводную таблицу channel_subcategory и добавил такое отношение:

public function up()
{
    Schema::create('channel_subcategory', function (Blueprint $table) {
        $table->increments('id');
        $table->timestamp('created_at')->useCurrent();
        $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        $table->integer('channel_id')->unsigned()->nullable();
        $table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
        $table->integer('subcategory_id')->unsigned()->nullable();
        $table->foreign('subcategory_id')->references('id')->on('subcategories') ->onDelete('cascade');
    });
}


I want to get one channel given the slug property and the subcategories it belongs to. So I did this in the ChannelController.php

 public function show($slug)
{
    $channel = Channel::where('channels.slug', '=', $slug)->first();
    foreach ($channel as $subcategory) {
        echo $subcategory->title;
    }
}

I get the error:

ErrorException in ChannelController.php line 107: Trying to get property of non-object


All I want is to show the channel name and the categories it belongs to.

Я прочитал много блогов, в том числе документацию Laravel, и они всегда объясняют миграции, как установить связь в модели (принадлежит многим) и даже как сохранить связанные данные. Но нигде я не нашел ни единого описания (для чайников), которое говорит, что теперь давайте возьмем некоторые данные из двух таблиц, например:

  • get all the categories one channel belongs to.
    • get all the channels in one category
    • получить все каналы, принадлежащие более чем к одной категории
    • получить категорию с большим количеством каналов.

Другими словами, простое объяснение того, как это сделать.

ИЗМЕНИТЬ Добавление модели моего канала

public function subcategory()
{
    return $this->belongsToMany('App\Subcategory')->withTimestamps();
}

person Rafael Munoz    schedule 02.06.2017    source источник


Ответы (1)


Вам необходимо определить отношения в ваших моделях. В вашем случае вы должны создать отношение subcategories в модели Channel.

public function subcategories()
{
    return $this->belongsToMany(Subcategory::class, 'channel_subcategory', 'channel_id', 'subcategory_id')->withTimestamps();
}

Измените SubCategory на то, что вы назвали модели.

Затем в вашем контроллере вы можете получить доступ к таким отношениям

$channel = Channel::where('slug', $slug)->first();

foreach ($channel->subcategories as $subcategory) {
    echo $subcategory->title;
}

Хотя приведенный выше код работает, вы всегда должны стремиться к загрузке, если вам понадобятся данные о взаимосвязях. Это предотвращает проблему с запросом N + 1.

$channel = Channel::with('subcategories')->where('slug', $slug)->first();
person Sandeesh    schedule 02.06.2017
comment
Я отредактировал свой вопрос с помощью своей модели канала. Это неправильно? Если я получаю var_dump, я вижу имя канала, а также имя категорий, к которым он принадлежит. Моя проблема, я думаю, заключается в том, чтобы повторить название подкатегории. Поэтому он говорит: Попытка получить свойство не-объекта - person Rafael Munoz; 02.06.2017
comment
Цикл в вашем вопросе проходит через $channel, который не является подкатегориями. Проверьте цикл, который я показал. Также исправлена ​​связь в моем коде. Я сделал ошибку при изменении полей отношений из примера. - person Sandeesh; 02.06.2017
comment
Спасибо чувак!!!. Работает после нескольких дней попыток! Между прочим: знаете ли вы какой-нибудь учебник, в котором я мог бы объяснить это и построить такие запросы, которые я опубликовал? (все каналы в категориях, категории с дополнительными каналами, каналы без категорий и т. д.)? Принимаю твой ответ. Спасибо еще раз - person Rafael Munoz; 02.06.2017
comment
То, о чем вы спрашиваете, очень просто. Поначалу это может показаться очень сложным, но станет легко, когда вы напишете свои первые отношения. В официальной документации есть хорошая информация о том, что вам нужно laravel.com/docs/ 5.4 / красноречивые-отношения # многие-ко-многим. Единственное, что вам нужно знать, это активная загрузка и проверки взаимосвязей, то есть with(), load(), has() и whereHas(). Вот несколько хороших руководств. - person Sandeesh; 02.06.2017