Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Dave Wize's avatar

Sort by recently retreived

Hay everyone.

I would love some input on the best way to implement a sort by recent views.

I don't want to task every model retrieval with an update to the database, but I would love to sort tables by recently viewed.

The session is probably not the solution as well since I want to do regular eloquent queries for the retrieval and not retrieve from the session.

Is there a package for this?

0 likes
2 replies
LaryAI's avatar
Level 58

To implement a "sort by recent views" feature without updating the database on every model retrieval, you can use a combination of caching and a separate table to track views. Here's a step-by-step solution:

  1. Create a Views Table: Create a new table to store the view counts and timestamps for each model.
php artisan make:migration create_views_table --create=views

In the migration file:

Schema::create('views', function (Blueprint $table) {
    $table->id();
    $table->morphs('viewable'); // This will allow the table to be used for multiple models
    $table->integer('views')->default(0);
    $table->timestamps();
});
  1. Create a Viewable Trait: Create a trait to handle the view logic.
namespace App\Traits;

use App\Models\View;

trait Viewable
{
    public function views()
    {
        return $this->morphOne(View::class, 'viewable');
    }

    public function incrementViews()
    {
        $view = $this->views()->firstOrCreate([]);
        $view->increment('views');
        $view->touch(); // Update the timestamp
    }
}
  1. Use the Trait in Your Models: Use the Viewable trait in the models you want to track views for.
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Traits\Viewable;

class Post extends Model
{
    use Viewable;
}
  1. Increment Views on Retrieval: Increment the view count when the model is retrieved.
$post = Post::find($id);
$post->incrementViews();
  1. Sort by Recently Viewed: To sort by recently viewed, you can join the views table and order by the updated_at column.
use App\Models\Post;
use App\Models\View;

$posts = Post::leftJoin('views', function($join) {
    $join->on('posts.id', '=', 'views.viewable_id')
         ->where('views.viewable_type', '=', Post::class);
})
->orderBy('views.updated_at', 'desc')
->get();

This approach ensures that you are not updating the main model's table on every view, but rather a separate views table. This also allows you to sort by the most recently viewed items efficiently.

Please or to participate in this conversation.