Skip to content

davidjr82/eloquent-viewable

 
 

Repository files navigation

Eloquent Viewable

Packagist Travis branch StyleCI Codecov branch Total Downloads license

This Laravel >= 5.5 package allows you to associate views with Eloquent models.

Once installed you can do stuff like this:

// Get the total number of views
$post->getViews();

// Get the total number of views since the given date
$post->getViews(Period::since(Carbon::parse('2014-02-23 00:00:00')));

// Get the total number of views between the given date range
$post->getViews(Period::create(Carbon::parse('2014-00-00 00:00:00'), Carbon::parse('2016-00-00 00:00:00')));

// Get the total number of views in the past 6 weeks (from today)
$post->getViews(Period::pastWeeks(6));

// Get the total number of views in the past 2 hours (from now)
$post->getViews(Period::subHours(2));

// Store a new view in the database
$post->addView();

Overview

Eloquent Viewable is a powerful, flexible and easy to use Laravel package to associate views with Eloquent Models. It's designed to be fast, flexible, and useful for various projects.

This package is not built with the intent to collect analytical data. It is made to simply store the views of a Laravel Eloquent model. You would this package for models like: Post, Video, Course and Hotel, but of course, you can use this package as you want.

Features

Here are some of the main features:

  • Associate views with Eloquent models
  • Get the total number of (unique) views
  • Get the total number of (unique) views since a specific date
  • Get the total number of (unique) views upto a specific date
  • Get the total number of (unique) views between two dates
  • Get the total number of (unique) views in the past days, weeks, months and years from today
  • Get the total number of (unique) views in the past seconds, minutes, hours, days, weeks, months and years from now
  • Cache the retrieved views counts
  • Queue the views before saving them in the database to prevent slow requests

Feature requests are very welcome! Create an issue with [Feature Request] as prefix or send a pull request.

Documentation

In this documentation, you will find some helpful information about the use of this Laravel package. If you have any questions about this package or if you discover any security-related issues, then feel free to get in touch with me at [email protected].

Table of contents

  1. Getting Started
  2. Usage
  3. Configuration
  4. Recipes

Getting Started

Requirements

The Eloquent Viewable package requires PHP 7+ and Laravel 5.5+.

Lumen is not supported!

Version information

Version Illuminate Status PHP Version
3.0 5.5 - 5.7 In Development >= 7.1.0
2.0 5.5 - 5.7 Active support >= 7.0.0
1.0 5.5 - 5.6 Bug fixes only >= 7.0.0

Installation

You can install this package via composer using:

composer require cyrildewit/eloquent-viewable

Optionally, you can add the service provider in the config/app.php file. Otherwise this can be done via automatic package discovery.

// config/app.php

'providers' => [
    // ...
    CyrildeWit\EloquentViewable\EloquentViewableServiceProvider::class,
];

You can publish the migration with:

php artisan vendor:publish --provider="CyrildeWit\EloquentViewable\EloquentViewableServiceProvider" --tag="migrations"

After publishing the migration file you can create the views table by running the migrations. However, if you already have a table named views, you can change this name in the config. Search for 'models->view->table_name' and change the value to something unique.

php artisan migrate

You can publish the config file with:

php artisan vendor:publish --provider="CyrildeWit\EloquentViewable\EloquentViewableServiceProvider" --tag="config"

Usage

In the following sections, you will find information about the usage of this package.

Preparing your models

To make an Eloquent model viewable just add the Viewable trait to your model definition. This trait provides various methods to allow you to save views, retrieve views counts and order your items by views count.

use Illuminate\Database\Eloquent\Model;
use CyrildeWit\EloquentViewable\Viewable;

class Post extends Model
{
    use Viewable;

    // ...
}

Storing views

Adding a new view to a model can be achieved really easy by calling the ->addView() method on your viewable model.

The best place where you should put it is inside your controller. If you're following the CRUD standard, it would be the @show method.

$post->addView();

A PostController might look something like this:

// ...
public function show(Post $post)
{
    $post->addView();

    return view('blog.post', compact('post'));
}
// ...

Note: If you want to queue this job, you can turn this on in the configuration! See the Queue the ProcessView job section!

Saving views with expiry date

If you want to add a delay between views from the same session, you can use the available addViewWithExpiryDate on your viewable model.

$post->addViewWithExpiryDate(Carbon::now()->addHours(2));

This method will add a new view to your model and it will add a record in the user's session. If you call this method multiple times, you will see that views count will not increment. After the current date time has passed the expiry date, a new view will be stored.

Retrieving views counts

After adding the Viewable trait to your model, you will be able to call getViews() and getUniqueViews() on your viewable model. Both methods accepts an optional Period instance.

/**
 * Get the total number of views.
 *
 * @param  \CyrildeWit\EloquentViewable\Support\Period
 * @return int
 */
public function getViews($period = null): int;

/**
 * Get the total number of unique views.
 *
 * @param  \CyrildeWit\EloquentViewable\Support\Period
 * @return int
 */
public function getUniqueViews($period = null) : int;

Period class

Be aware that the following code isn't valid PHP syntax!

// Create a new Period instance.
Period::create(DateTime $startDateTime = null, DateTime $endDateTime = null);

// Create a new Period instance with only a start date time.
Period::since(DateTime $startDateTime);

// Create a new Period instance with only a end date time.
Period::upto(DateTime $endDateTime);
// Period instance with a start date time of today minus the given days.
Period::pastDays(int $days);

// Period instance with a start date time of today minus the given weeks.
Period::pastWeeks(int $weeks);

// Period instance with a start date time of today minus the given months.
Period::pastMonths(int $months);

// Period instance with a start date time of today minus the given years.
Period::pastYears(int $years);
// Period instance with a start date time of now minus the given seconds.
Period::subSeconds(int $seconds);

//Period instance with a start date time of now minus the given minutes.
Period::subMinutes(int $minutes);

// Period instance with a start date time of now minus the given hours.
Period::subHours(int $hours);

// Period instance with a start date time of now minus the given days.
Period::subDays(int $days);

// Period instance with a start date time of now minus the given weeks.
Period::subWeeks(int $weeks);

// Period instance with a start date time of now minus the given months.
Period::subMonths(int $months);

// Period instance with a start date time of now minus the given years.
Period::subYears(int $years);

Examples

$post->getViews();

$post->getViews(Period::since(Carbon::parse('2007-05-21 12:23:00')));

$post->getViews(Period::upto(Carbon::parse('2013-05-21 00:00:00')));

$post->getViews(Period::create(Carbon::parse('2014-00-00 00:00:00'), Carbon::parse('2016-00-00 00:00:00')));
$post->getUniqueViews();

$post->getUniqueViews(Period::since(Carbon::parse('2007-05-21 12:23:00')));

$post->getUniqueViews(Period::upto(Carbon::parse('2013-05-21 00:00:00')));

$post->getUniqueViews(Period::create(Carbon::parse('2014-00-00 00:00:00'), Carbon::parse('2016-00-00 00:00:00')));
$post->getViews(Period::pastDays(5));

$post->getViews(Period::pastWeeks(6));

$post->getViews(Period::pastMonths(8));

$post->getViews(Period::pastYears(3));
$post->getUniqueViews(Period::pastDays(5));

$post->getUniqueViews(Period::pastWeeks(6));

$post->getUniqueViews(Period::pastMonths(8));

$post->getUniqueViews(Period::pastYears(3));
$post->getViews(Period::subSeconds(30));

$post->getViews(Period::subMinutes(15));

$post->getViews(Period::subHours(8));

$post->getViews(Period::subDays(5));

$post->getViews(Period::subWeeks(6));

$post->getViews(Period::subMonths(8));

$post->getViews(Period::subYears(3));
$post->getUniqueViews(Period::subSeconds(30));

$post->getUniqueViews(Period::subMinutes(15));

$post->getUniqueViews(Period::subHours(8));

$post->getUniqueViews(Period::subDays(5));

$post->getUniqueViews(Period::subWeeks(6));

$post->getUniqueViews(Period::subMonths(8));

$post->getUniqueViews(Period::subYears(3));

Order models by views count

Retrieve Viewable models by views count

$sortedPosts = Post::orderByViewsCount()->get(); // desc
$sortedPosts = Post::orderByViewsCount('asc')->get();

Retrieve Viewable models by unique views count

$sortedPosts = Post::orderByUniqueViewsCount()->get(); // desc
$sortedPosts = Post::orderByUniqueViewsCount('asc')->get();

ViewTracker helper

Get views by viewable type

use CyrildeWit\EloquentViewable\ViewTracker;

// Get the total number of views of one type
ViewTracker::getViewsCountByType(Post::class);

// Get the total number of views of multiple types
ViewTracker::getViewsCountByTypes([Post::class, Location::class, Hotel::class]);

Configuration

Queue the ProcessView job

When calling the ->addView() method on your model, it will save a new view in the database with some data. Because this can slow down your application, you can turn queuing on by changing the value of store_new_view under jobs in the configuration file. Make sure that your app is ready for queuing. If not, see the official Laravel documentation for more information!

Extending

If you want to extend or replace one of the core classes with your own implementations, you can override them:

  • CyrildeWit\EloquentViewable\View
  • CyrildeWit\EloquentViewable\ViewableService
  • CyrildeWit\EloquentViewable\CrawlerDetector\CrawlerDetectAdapter

Note: Don't forget that all custom classes must implement their original interfaces

Replace View model with custom implementation

$this->app->bind(
    \CyrildeWit\EloquentViewable\Contracts\View::class,
    \App\Models\CustomView::class
);

Replace ViewableService service with custom implementation

$this->app->singleton(
    \CyrildeWit\EloquentViewable\Contracts\ViewableService::class,
    \App\Services\CustomViewableService::class
);

Replace CrawlerDetectAdapter class with custom implementation

$this->app->singleton(
    \CyrildeWit\EloquentViewable\Contracts\CrawlerDetector::class,
    \App\Services\CrawlerDetector\CustomAdapter::class
);

Recipes

Creating helper methods for frequently used period formats

App\Models\Post

// ...

public function getViewsSince(DateTime $sinceDateTime)
{
    return $this->getViews(Period::since($sinceDateTime));
}

public function getViewsUpto(DateTime $uptoDateTime)
{
    return $this->getViews(Period::upto($uptoDateTime));
}

public function getViewsBetween(DateTime $sinceDateTime, DateTime $uptoDateTime)
{
    return $this->getViews(Period::create($sinceDateTime, $uptoDateTime));
}

public function getViewsInPastDays(int $days)
{
    return $this->getViews(Period::pastDays($days));
}

// ...

resources/views/post/show.blade.php

<!-- ... -->

Page views since 2014: {{ $post->getViewsSince(Carbon::create(2014)) }}
Page views upto 2016: {{ $post->getViewsUpto(Carbon::create(2016)) }}
Page views between 2016 - 2018: {{ $post->getViewsBetween(Carbon::create(2016), Carbon::create(2018)) }}

Page views in the past 5 days: {{ $post->getViewsInPastDays(5) }}

<!-- ... -->

Upgrading

Please see UPGRADING for detailed upgrade guide.

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Credits

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

About

Associate views with Eloquent models in Laravel

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%