1
votes

I'm building a simple shop catalog in Laravel 5.4. Basically, what I want is to have a button on my article that gets all articles with the related categories (noting that an article can have many categories).

I have my Article and Category models, as well as an article_category pivot table. Both have a belong to many relationship to the other, like:

Code in Article model:

public function categories()
{
    return $this->belongsToMany('App\Category');
}

Code on Category model:

public function articles()
{
    return $this->belongsToMany('App\Article');
}

My issue is how to get the list of articles that include all articles with categories related to an article.

This is my function on the controller right now, it receives a JSON object with a list of categories:

public function showRelatedArticles($category) 
{
    // Decode JSON to PHP array
    $category = json_decode($category);
    $collection;
    if(is_array($category)){
        foreach ($category as $cat) {
            $articles = Article::whereHas('Category', function ($query) {
                $query->where('category_id', $cat->id);
            })->get();
            $collection = merge($articles);
        }
    } else {
        dd('Not array');
    }

    return view('front', ['articles' => $collection]);
}

This returns an error:

BadMethodCallException
Call to undefined method Illuminate\Database\Query\Builder::Category()

I may have the wrong type of relation between my models, but this is the correct method of declaring a Many to Many relationship, no?

1
whereHas('categories',?Felippe Duarte
Thanks Felippe Duarte, you might be onto something, I should be using 'categories' instead of 'category'. Unfortunately I cant seem to use $cat inside the function, it gives me an 'undefined variable' error. passing a second parameter to the function seems to break it, how should I proceed?TianRB
function ($query) use($cat) { Felippe Duarte

1 Answers

2
votes

You could rewrite the whole part to this:

if (is_array($category)){
    $category_ids = collect($category)->pluck('id');

    $articles = Article::whereHas('categories', function($query) use ($category_ids) {
        // Assuming your category table has a column id
        $query->whereIn('categories.id', $category_ids);
    })->get();
} else {
    dd('Not array');
}

Note the lowercase categories, which is the function name in the Article class.

This combines the in from the queries, the collect for array's and only retrieves the articles which are linked to the given categories.