Creating a star rating percentage in Laravel
Okay, so you have a star based rating system out of 5 stars. I'm going to make a few assumptions/suggestions below.
I assume you have a ratings table that literally just stores one row per rating, if not, I'd recommend setting one up.
<?php
class Rating extends \Eloquent
{
protected $fillable = ['profile_id', 'user_id', 'rating'];
public function user()
{
return $this->belongsTo('User', 'user_id');
}
public function profile()
{
return $this->belongsTo('Profile', 'profile_id');
}
}
This table will serve as a good way to keep track of ratings, plus it allows you to limit ratings if you add timestamps and some logic in your controller.
You've got several options here, and they are as follows.
- Have a column on the profile which contains the current rating, and is updated when a new rating is added.
- Have a summary table that contains the rating and is updated when a new rating is added.
- Dynamically work it out.
The way to work out the rating for option 1 would be the same as option 3, except you'd only run it once a new rating was added. Take the below pseudo code.
rating = score / ((total_ratings * 5) / 100)
In this example, score
is the sum of all ratings and total_ratings is the count of ratings.
Rather than have the code in your controller, you could abstract it out to a Laravel mutator in the model, which for a dynamic value would look like the following:
public function getRating()
{
return Profile::join('ratings', 'ratings.profile_id', '=', 'profile.id')
->where('profile.id', $this->attributes['id'])
->select(DB::raw('SUM(ratings.rating) / ((COUNT(ratings.* * 5) / 100) as rating'))->pluck('rating');
}
Now when accessing your profile/supplier model, you can just access the rating property like you would any other column.
If you wanted this to be stored, you'd use the same sort of method to work it out in the controller. Ultimately you're not limited to any particular method, and there are more than three that I mentioned, but those are the base ones.
Hope that helps.
Jono20201
Software engineer specialising in web-based apps, SaaS solutions and, cloud infrastructure. If you need more help than StackOverflow provides then I do provide a reasonably priced consultancy service. Contact: jono20201[at]gmail[dot]com
Updated on June 04, 2022Comments
-
Jono20201 over 1 year
I am creating an application where buyers can rate their supplier against a project, they rate them on a 'out of five' basis (with stars) however on the supplier profile I want to display this data as a normal percentage. I have gotten this to work with this following code, but I wanted to know if there was a cleaner way to do this as It seems I would have to replicate this code 5 times (or create a function for it) but I was hoping Laravel may have a better way to do it.
public function getSupplierProfile($group_id) { $group = Group::findOrFail($group_id); $data = new stdClass; $data->quality = new stdClass; $data->quality->query = SupplierRating::where('supplier_id', '=', $group->id); $data->quality->count = $data->quality->query->count(); $data->quality->star_avg = $data->quality->query->avg('quality'); $data->quality->avg = $data->quality->star_avg / ($data->quality->count * 6) * 100; dd($data->quality->avg); // debug return View::make('groups.view_profile', array('group' => $group)); }
-
The Alpha over 9 yearsYou are passing
$group
to the view then why all the$data
? -
Jono20201 over 9 yearsCurrently just working on how to best pass the actual percent data to the view so it can be easily displayed, I will move all the processing into the Group or SupplierRating model once I have it figured.
-
Arthur BALAGNE over 9 yearsFor me, the easiest way to do that, is to create an attribute $data fill it with whatever you need in the __contruct function.
-
Jarek Tkaczyk over 9 yearsHave you thought about scalability? How would you present these ratings for a list of
suppliers
? What you have now leads to queryingratings
table for everysupplier
on the list. You'd better do the math on the DB side, only then setup accessor for that percentage rating. -
Jono20201 over 9 years@deczo At no point will these values be presented in a list with lots of suppliers, that's something our application explicitly doesn't want. If for some reason we do start listing them I would cache the values in the suppliers database table.
-