filter results based on model method

2019-09-07 21:13发布

问题:

I have these models, Venue, Review, User. a User can score several venues.
A venue has many reviews A review belongs to a venue and user

on my Venue model I have a method which calculates score of a venue:

public function score()
{
    $reviewCount = $this->reviews()->count();
    $qualitySum = $this->reviews()->sum('quality') * 2;
    $decorSum = $this->reviews()->sum('decor');
    $venueAverage = ($qualitySum + $decorSum) / ($reviewCount * 30);
    $minReview = 5;
   //based on weighted average and Barnsley  average
    $average = ($reviewCount * Review::R()) / ($reviewCount + $minReview) + ($minReview * $venueAverage) / ($reviewCount + $minReview);
    $average = round($average, 1);
    return $average;
}

Here is the question: How can I retrieve those venues which score is >3
And how can I order results based on score

回答1:

Looking at http://laravel.com/docs/5.1/eloquent-relationships they use the following example:

// Retrieve all posts with at least one comment containing words like foo%
$posts = Post::whereHas('comments', function ($query) {
    $query->where('content', 'like', 'foo%');
})->get();

Based on above, you should be able to put the constraint into your "reviews" whereHas function:

$venues = Venue::whereHas('location', function ($query) use ($city) {
        $query->whereCityId($city->id);
    })
        ->whereHas('cuisines', function ($query) use ($cuisine) {
            $query->whereName($cuisine);
        })
        ->whereHas('reviews',function($query) use ($minCount)
        {
            $query->where('score', '>', 3);
        })
        ->take(3)->get();

You can also get the count by adding ->count() either before or after ->get(), depending on your use case.