vitorenes's avatar

Filtering Eloquent with multiple belongsToMany relationships

Hello, everyone. As a total n00b in regards to Eloquent, which I still think is some sort (amazing!) of Voodoo stuff, I would appreciate any help with the following:

I have a CONTENT model that "handles" the main data for a given video file; I also have a CATEGORY model and a SUBCATEGORY model.

A CONTENT piece belongs to many CATEGORIES and SUBCATEGORIES, and I can, of course, fairly easily get, say, all CONTENT pieces for a given CATEGORY by doing something like

$allContent=App\Category::where('id', '1')->first()->contents which gets me ALL CONTENT that belongs to that category.

Now, let's say I have the need to "group" or "filter" that resulting collection by SUBCATEGORY, i.e., once I have all the CONTENT that belongs to a CATEGORY (obtained as explained before), I would like to do something like:

$filteredContent = $allContent->where('subcategories', '3')->get()

where 'subcategories' is the relationship that declares that CONTENT also belongs to many SUBCATEGORIES, and where I say that I want only CONTENT from that collection that belongs to SUBCATEGORY with ID = 3

Again, being a total n00b with this stuff, I am VERY confused as to how I could achieve this. I GUESS it might also be possible to get all SUBCATEGORY content, like:

App\SubCategory::where('id', '1')->first()->contents

And then get ONLY the CONTENT in that collection that belongs to CATEGORY x.

ANY help will be ENORMOUSLY appreciated, so, thanks in advance! P.S.: Please feel free to "insult" me in case this provided info is not enough for you to be able to answer - let me now how much of an additional noob I am by clearly stating it :-)

0 likes
2 replies
SilenceBringer's avatar
Level 55

Hi @vitorenes I think whereHas condition is what you looking for.

So, you can grab all the contents which have specific subcategory like

App\Content::whereHas('subcategories', function ($query) {
    $query->where('id', 3);
})->get();

and even more filter by category and subcategory

App\Content::whereHas('subcategories', function ($query) {
    $query->where('id', 3);
})
    ->whereHas('categories', function ($query) {
        $query->where('id', 1);
    })
    ->get();
1 like
vitorenes's avatar

@silencebringer You, Sir, win all te points today. THANK YOU so much. That is, in fact, what I was looking for. Just in case some other inexperienced guy (like myself) comes across this, here is a little confusing factoid I had to overcome:

When trying to build the code to filter my results, I found myself in need of passing some parameters to that wonderful piece of code you wrote in your example. Being ignorant, I tried to pass it as another argument of the closure function, only to find it threw an error; the correct way to pass parameters to that closure is by way of the "use" keyword, as in:

$content = Content::
	whereHas('subcategories', 
		function ($query) use($sub_category_id) {
            		$query->where('sub_category_id', $sub_category_id);
        	})
	->whereHas('categories', 
		function($query) use($category_id) {
            		$query->where('category_id', $category_id);
        	})
->get();

Again, thank you very much for your answer.

Please or to participate in this conversation.