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

OccultScientist's avatar

Article view counter for various models by date

Hi,

I'm trying to think of the best way to record article views for different article types (e.g News Article, Review, etc...), to use the data for most popular articles today/in the last week/etc and for admin dashboard stats.

What is the best way to do this? I was leaning toward a polymorphic relationship with a new table called stats:

id, date, view_count, viewable_id, viewable_type

but my brain is farting on the best way to update the data when a page is viewed.

Can anyone help me out?

0 likes
4 replies
Tray2's avatar

There are quite a few external tools that you can use, otherwise I would use something like a visits table that contains these columns

  • id
  • post_id
  • visitor_ip
  • created_at *updated_at

Then I would store each view in that table if the visitor_ip doesn't already exists in the table.

Then each early morning I would convert each visit into a summed value, and remove all the other rows for that day.

Then you can query the table to see visit each day, month, year and total.

1 like
OccultScientist's avatar

@Tray2 Thanks for your reply. How would you handle the different model types? The problem I'm having is that they can have the same id value and that would mess with my stats

achatzi's avatar

@OccultScientist Have a look at polymorphic relationships https://laravel.com/docs/10.x/eloquent-relationships#polymorphic-relationships

A model can have the same relationship with multiple different models.

Edit: added example

Your scema

articles
    id - integer
    title - string
    body - text
 
reviews
    id - integer
    title - string
    body - text
 
visits
    id - integer
   visitor_ip - text
    visitable_id - integer
    visitable_type - string

Your classes

namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
 
class Visit extends Model
{
    /**
     * Get the parent visitable model (article or review).
     */
    public function visitable(): MorphTo
    {
        return $this->morphTo();
    }
}
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
 
class Article extends Model
{
    /**
     * Get all of the article's visits.
     */
    public function visits(): MorphMany
    {
        return $this->morphMany(Visit::class, 'visitable');
    }
}
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
 
class Reviews extends Model
{
    /**
     * Get all of the review's visits.
     */
    public function visits(): MorphMany
    {
        return $this->morphMany(Visit::class, 'visitable');
    }
}
1 like

Please or to participate in this conversation.