Saad Suri
Saad Suri

Reputation: 1382

Call to undefined relationship on model laravel using scope

I'm trying to get 5 posts for each category so I did a little search and ends up here Getting n Posts per category But I'm getting a weird Call to undefined relationship on model when using with scope but it all works fine If I don't use a scope. Here is the Category Model

   //Relationship with posts
    public function posts(){
        return $this->hasMany('App\Post');
    }

scopeNPerGroup

public function scopeNPerGroup($query, $group, $n = 10)
    {
        // queried table
        $table = ($this->getTable());

        // initialize MySQL variables inline
        $query->from( \DB::raw("(SELECT @rank:=0, @group:=0) as vars, {$table}") );

        // if no columns already selected, let's select *
        if ( ! $query->getQuery()->columns) 
        { 
            $query->select("{$table}.*"); 
        }

        // make sure column aliases are unique
        $groupAlias = 'group_'.md5(time());
        $rankAlias  = 'rank_'.md5(time());

        // apply mysql variables
        $query->addSelect(\DB::raw(
            "@rank := IF(@group = {$group}, @rank+1, 1) as {$rankAlias}, @group := {$group} as {$groupAlias}"
        ));

        // make sure first order clause is the group order
        $query->getQuery()->orders = (array) $query->getQuery()->orders;
        array_unshift($query->getQuery()->orders, ['column' => $group, 'direction' => 'asc']);

        // prepare subquery
        $subQuery = $query->toSql();

        // prepare new main base Query\Builder
        $newBase = $this->newQuery()
            ->from(\DB::raw("({$subQuery}) as {$table}"))
            ->mergeBindings($query->getQuery())
            ->where($rankAlias, '<=', $n)
            ->getQuery();

        // replace underlying builder to get rid of previous clauses
        $query->setQuery($newBase);
    }

Calling Npergroup with relation

public function latestposts()
    {
        return $this->posts()->latest()->nPerGroup('category_id', 5);
    }

Post Model Relationship

//Post belongs to Category
 public function category(){
        return $this->belongsTo('App\Category');
    }

In my category controller I'm calling latestposts through

$categories = Category::with('latestposts')->get();

But I'm getting the error: Call to undefined relationship on model

What I want is: Get the N number of posts per each category but I'm completely lost at this point. Any help would be appreciated

Reference: Tweaking Eloquent relations – how to get N related models per parent ?

Upvotes: 5

Views: 6935

Answers (1)

Chirag Patel
Chirag Patel

Reputation: 1642

I am giving this answer based on your purpose that you want 5 posts per category. So you have Category Model and Post Model.

And in Category Model you have relation with Post model like this

    //Relationship with posts
    public function posts(){
        return $this->hasMany('App\Post');
    }

And in Post Model you have relation with Category model like this

//Post belongs to Category
 public function category(){
        return $this->belongsTo('App\Category');
    }

I show your question you have done SQL queries.

Instead of that, You can use two approaches

1) Give condition while eagar loading

$categories = Category::with(['posts' => function ($query) {
    $query->orderBy('created_at', 'desc')->take(5);
}])->get();

Note: This approach will only work when you take only one result of parent child using first() method.

To get n number of posts per category Use this.

First, you can retrieve all categories with

$categories = Category::all();

Then you can use foreach loop and in all $category you have to give assign new attribute in it like here latestposts,

foreach ($categories as $category)
{
    $category->latestposts = $category->posts()->orderBy('created_at','desc')->take(5)->get();
}

After this foreach loop you will get latest 5 posts in all categories.

Try this in your code and comment your queries and reviews.

Upvotes: 3

Related Questions