Rafael Munoz
Rafael Munoz

Reputation: 656

Laravel> Using Eloquent Querying many-to-many relations

I am trying to figure out how does the Eloquent works and the advantages over using plain sql queries (join A and B tables on columA.id = columnB.id...)

I have two models: channels and subcategories in a many-to-many relation

I created a channel_subcategory pivot table and addded the relation like this:

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.

I have read lots of blogs, including the Laravel documentation and they always explain migrations, how to establish the relation in the model (belongstomany), and even how to save related data. But nowhere I found a single description (for dummies) that tell, well now lets get some data out of the two tables like:

In other words, a plain explanation on how to do this.

EDIT Adding my Channel model

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

Upvotes: 1

Views: 939

Answers (1)

Sandeesh
Sandeesh

Reputation: 11906

You need to define the relationship in your models. In your case you should create a subcategories relationship in the Channel model.

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

Change SubCategory to whatever you've named the model.

Then in your controller you can access the relationship like this

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

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

Though the above code works, you should always eager load if you're going to need relationship data. This prevents the N+1 query issue.

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

Upvotes: 1

Related Questions