jpeterson579's avatar

Get average review for Reviews model within model...?

Hi All,

I am trying to calculate the average rating in my product model however getting the following error. No idea what is going on as this seems like it should work...

Call to a member function addEagerConstraints() on float

Product Model

public function reviews()
{
    return $this->hasMany('App\Review');
}


public function avgReviewRating()
{
    return $this->reviews()->avg('rating');
}

Also, I am trying to avoid loading all data for every review in my view. I just want to do the calculation for each product and display the result.

0 likes
8 replies
staudenmeir's avatar

How are you using avgReviewRating()? Are you trying eager loading?

jpeterson579's avatar

@staudenmeir So in my controller I use

public function homepage()
{
    $products = Product::inRandomOrder()->with('firstPhoto', 'avgReviewRating')->take(10)->get();
    return view('homepage', compact('products'));
}
Cronix's avatar

Show where you're using it. avg() actually executes the query and returns a float value. It sounds like you're trying to use it within a relationship constraint, which won't work because it doesn't return a builder instance to chain onto.

Edit: you just posted your code and that's the issue. avgReviewRating is not a relationship, so you can't use it in a with.

Cronix's avatar

This will probably do what you're wanting

public function homepage()
{
    $products = Product::inRandomOrder()->with('firstPhoto', 'reviews')->take(10)->get();
    return view('homepage', compact('products'));
}
@foreach ($products as $product)
    Rating:: {{ $product->avgReviewRating() }}
@endforeach 
jpeterson579's avatar

@cronix So since $products is going to return 10 random products how do I attach just the average review?

If I eager load my reviews model that is going to load every review in the view and I don't want that. I just want the avg number...

staudenmeir's avatar

You can modify withCount():

$products = Product::inRandomOrder()->with('firstPhoto')->take(10)
    ->withCount(['reviews as reviews_avg' => function($query) {
        $query->select(DB::raw('avg(rating)'));
    }])
    ->get();
5 likes
Naqi's avatar

@staudenmeir Thanks, 6 years ago yet really helpful. I ended up using the withAvg() method

Please or to participate in this conversation.