I'm trying to sort an Eloquent ORM call based on the result of a method defined in a related model. I'm using Laravel 5.
I want a list of posts
including the posts author
, location
, comments
and counts
(which is a count of views
, upvotes
and downvotes
for a post). I want the list sorted by hotness
, which is not a field in the db (the result of a function).
In the \App\Counts
model we have a method called hotness()
This method performs a calculation on an algorithm similar to the reddit algorithm [see below for details]
I have a an Eloquent ORM call:
$posts = \App\Post::with('author')
->with('location.city')
->with('comments')
->with('counts')
->paginate(20);
The \App\Counts
model contains fields for upvotes
, downvotes
, views
, and a few other variables that are used when calculating the hotness of the post.
I can add the hotness
value to the array that comes back from the counts
model when paginating (on the fly) by overriding the toArray()
method in my model like this:
public function toArray()
{
$array = parent::toArray();
$array['hotness'] = $this->hotness();
return $array;
}
While this is useful in its own right, I can't achieve my objective, which is to sort the ORM paginated result by each posts hotness
rating.
Is there any way I can achieve this without having a cron go through all the posts and calculate the hotness
for each post every x minutes?
I would ideally like to be able to just add
->orderBy('hotness')
or
->orderBy('counts.hotness')
but I have a feeling this might not be possible.
Any creative ideas around how to solve this?
Hotness Algorithm for reference
T
is the time in seconds between when the post was made an the date of the first post on the website
x
is the number of upvotes minus the number of downvotes
y
is -1 if x < 0
, 0 if x = 0
and 1 if x > 0
z
is the absolute value of x
and 1