Show popular content from a specific period in Laravel
Table of contents:
# Introduction
When you visit online stores or blogs, you might have noticed that they often have sections like "Users also viewed" or "Popular products". For example, when you are in a product page, you might see a section like this:
It can be useful to show content such as the most visited for the last 24 hours on your website. This could help you to present more relevant resources to your users and increase user engagement.
In this article, we'll learn how to track views and get popular content (ordered by views) from a specific period in Laravel.
# Track views and fetch popular content from a specific period
# Install the cyrildewit/eloquent-viewable
package
To handle views, you need to install the cyrildewit/eloquent-viewable
package:
composer require cyrildewit/eloquent-viewable
Publish the migrations and run the migrate
command:
php artisan vendor:publish --provider="CyrildeWit\EloquentViewable\EloquentViewableServiceProvider" --tag="migrations"
php artisan migrate
Then, add the InteractsWithViews
trait to your model that you want to track views. The model should also implement the Viewable
interface:
use CyrildeWit\EloquentViewable\Contracts\Viewable;
use CyrildeWit\EloquentViewable\InteractsWithViews;
class Course extends Model implements Viewable
{
use InteractsWithViews;
}
# Record views
To make a view record after visiting our resource, you can dispatch a job after the response is sent to the browser:
dispatch(function () {
views($course)->record();
})->afterResponse();
# Show popular content from the last 24 hours
To show resources that have been viewed the most in the last 24 hours, you can use the orderByViews
method (it's a scope from InteractsWithViews
trait) that is used to order your models by the amount of views they have in a given period:
use App\Models\Course;
use CyrildeWit\EloquentViewable\Support\Period;
$courses = Course::orderByViews('desc', Period::subHours(24))
->take(20)
->get();
# Remove views older than 24 hours
If we only need to keep views in our database from the last day, we can extend the default View
model and use the Prunable
trait to delete views older than 24 hours:
<?php
declare(strict_types=1);
namespace App\Models;
use CyrildeWit\EloquentViewable\View as ViewModel;
use Illuminate\Database\Eloquent\Prunable;
class View extends ViewModel
{
use Prunable;
/**
* Get the prunable model query.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function prunable()
{
return static::where('viewed_at', '<=', now()->subHours(24));
}
}
In App\Http\Kernel.php
, schedule the model:prune
command to delete views older than 24 hours every day:
use App\Models\View;
$schedule->command('model:prune', [
'--model' => [View::class],
])->daily();
# Other periods
You can also use the Period
class to fetch popular content from other periods. For example, to fetch popular content from the last 7 days:
use CyrildeWit\EloquentViewable\Support\Period;
$courses = Course::orderByViews('desc', Period::subDays(7))
->take(20)
->get();
More periods are available in the Period
class, such as subMinutes
, subHours
, subDays
, subWeeks
, subMonths
, and subYears
. Check all in the official documentation.