根据相关模型中方法的结果对Eloquent ORM结果集进行排序

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

enter image description here

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

It seems that the functionality I'm looking for is not achievable.

I ended up persisting hotness to the counts table and update the value in the overriding toArray() method.

This allows me to ->orderBy('counts.hotness')

In order to mitigate overhead I use a cache key that expires after 15 minutes so that I'm not calculating the hotness each time the counts model is converted to an array.

I settled on 15 minutes as this allows the hotness to be fresh enough for the purposes of this application.