Top 10 Packages to Get More from Laravel Eloquent
Povilas Korop
Founder of QuickAdminPanel
At QuickAdminPanel, our goal is to save developer’s time. Laravel Eloquent is a good example of this – its “magic” helps to get things done faster. But on top of that, there are a lot of packages that can help even more. Let’s review the most popular ones.
Notice: some of the packages have a similar (almost identical) packages created by other developers, I’ve added those links at the end of each package review, where applicable.
1. Laravel Auditing: Record the change log from models
URL: http://laravel-auditing.com
Package that saves changes of your Eloquent model records as so-called “audits”, in a separate DB table.
Usage is very simple. All you need to do in your model:
use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;
class Article extends Model implements Auditable
{
use \OwenIt\Auditing\Auditable;
// ...
}
And then you can get all “audits” by your model:
// Get first available Article $article = Article::first(); // Get all associated Audits $all = $article->audits; // Get first Audit $first = $article->audits()->first(); // Get last Audit $last = $article->audits()->latest()->first(); // Get Audit by id $audit = $article->audits()->find(4);
Official website: laravel-auditing.com
Article on Laravel News: Track Laravel Model Changes with Laravel Auditing
Similar package: VentureCraft/revisionable
2. laravel-soft-cascade: Cascade Delete & Restore when using Laravel SoftDeletes
URL: https://github.com/Askedio/laravel-soft-cascade
Soft-deletes is a great Eloquent function out-of-the-box, but it doesn’t work with foreign keys and ->onDelete(‘cascade’); migration. This package will solve that problem.
Usage. In your model use this:
use \Askedio\SoftCascade\Traits\SoftCascadeTrait; protected $softCascade = ['profiles']; // names of your relations
After this, when you can soft-delete parent entry – all children entries will be automatically soft-deleted. It also works with restore() function:
User::first()->delete(); User::withTrashed()->first()->restore();
More info: Cascading SoftDeletes with Laravel 5
Similar package: michaeldyrynda/laravel-cascade-soft-deletes
3. spatie/laravel-schemaless-attributes: Add schemaless attributes to Eloquent models
URL: https://github.com/spatie/laravel-schemaless-attributes
This package provides a trait that when applied on a model, allows you to store arbritrary values in a single JSON column.
Preparing the model is a little more than one line of code, but still quite understandable, you need to define an attribute, accessor and scope:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\SchemalessAttributes\SchemalessAttributes;
class TestModel extends Model
{
// ...
public $casts = [
'extra_attributes' => 'array',
];
public function getExtraAttributesAttribute(): SchemalessAttributes
{
return SchemalessAttributes::createForModel($this, 'extra_attributes');
}
public function scopeWithExtraAttributes(): Builder
{
return SchemalessAttributes::scopeWithSchemalessAttributes('extra_attributes');
}
}
And then you can just use this attribute as a property inside your model:
$yourModel->extra_attributes->name = 'value'; $yourModel->extra_attributes->name; // Returns 'value'
Or as an array:
// All existing schemaless attributes will be replaced $yourModel->extra_attributes = ['name' => 'value']; $yourModel->extra_attributes->all(); // Returns ['name' => 'value']
4. awssat/laravel-visits: Track Model Visits
URL: https://github.com/awssat/laravel-visits
This package allows you to log visits to some page/model. It does that using Redis, so you need to configure this:
'laravel-visits' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 3, // anything from 1 to 15, except 0 (or what is set in default)
],
And then you can log visits with one line of code:
visits($post)->increment();
Counting the posts is also easy:
visits($post)->count();
It also has a logic of limiting the visit logging once per IP every 15 minutes, but it’s also configurable.
The best part comes if you want to aggregate data:
visits($post)->countries(); // top countries
visits($post)->refs(); // referers
visits('App\Post')->top(10); // Top 10 posts
More on Laravel News: Count Models With the Laravel Visits Package
5. cybercog/laravel-love: React on Eloquent models with Likes or Dislikes
URL: https://github.com/cybercog/laravel-love
If you have posts or comments that may be liked/disliked, this package is for you.
Preparation for the model looks like this:
use Cog\Contracts\Love\Likeable\Models\Likeable as LikeableContract;
use Cog\Laravel\Love\Likeable\Models\Traits\Likeable;
use Illuminate\Database\Eloquent\Model;
class Article extends Model implements LikeableContract
{
use Likeable;
}
And then you can do things like:
$user->like($article); $article->likeBy(); // current user $article->likeBy($user->id); $user->unlike($article); $article->unlikeBy(); // current user $article->unlikeBy($user->id); $article->likesCount; // get likes for article $article->collectLikers(); // Get collection of users who liked model
More on Laravel News: Laravel Love: Likes and Dislikes for Eloquent Models
6. spatie/laravel-tags: Add tags and taggable behaviour to your Laravel app
URL: https://github.com/spatie/laravel-tags
The only thing you have to do is add the HasTags trait to an Eloquent model to make it taggable.
use Spatie\Tags\HasTags;
class NewsItem extends Model
{
use HasTags;
...
}
And then feel free to use it:
//create a model with some tags
$newsItem = NewsItem::create([
'name' => 'testModel',
'tags' => ['tag', 'tag2'], //tags will be created if they don't exist
]);
//attaching tags
$newsItem->attachTag('tag3');
$newsItem->attachTags(['tag4', 'tag5']);
//syncing tags
$newsItem->syncTags(['tag1', 'tag2']); // all other tags on this model will be detached
//retrieving models that have any of the given tags
NewsItem::withAnyTags(['tag1', 'tag2'])->get();
//retrieve models that have all of the given tags
NewsItem::withAllTags(['tag1', 'tag2'])->get();
More info – in the article from the authors: An opinionated tagging package for Laravel apps
Similar package: rtconner/laravel-tagging
7. spatie/laravel-sluggable: Generate slugs when saving Eloquent models
URL: https://github.com/spatie/laravel-sluggable
This package automatically generates slugs from your title/name or whatever field you want. Here’s how you specify that in model:
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasSlug;
/**
* Get the options for generating the slug.
*/
public function getSlugOptions() : SlugOptions
{
return SlugOptions::create()
->generateSlugsFrom('name')
->saveSlugsTo('slug');
}
}
And then magic happens:
$model = new Article(); $model->name = 'activerecord is awesome'; $model->save(); echo $model->slug; // outputs "activerecord-is-awesome"
You can also specify different slugs for different languages, also configure what happens on updating the record, what separator to use (“-” or “_”) and more parameters.
More info from the authors: A PHP 7 / Laravel package to create slugs
Similar package: cviebrock/eloquent-sluggable
8. spatie/eloquent-sortable: Sortable behaviour for Eloquent models
URL: https://github.com/spatie/eloquent-sortable
This package provides a trait that adds sortable behaviour to an Eloquent model.
Here’s how you specify the sortable field in the model:
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
class Article extends Eloquent implements Sortable
{
use SortableTrait;
public $sortable = [
'order_column_name' => 'order_column',
'sort_when_creating' => true,
];
...
}
And then the column is filled in automatically:
$article = new Article(); $article->save(); // order_column for this record will be set to 1 $article = new Article(); $article->save(); // order_column for this record will be set to 2 $article = new Article(); $article->save(); // order_column for this record will be set to 3 //the trait also provides the ordered query scope $orderedRecords = Article::ordered()->get();
9. dimsav/laravel-translatable: A Laravel package for multilingual models
URL: https://github.com/dimsav/laravel-translatable
We have a separate article for 10 Best Laravel packages for multi-language projects, and this one is the obvious leader on the market.
You need to create database migrations according to this schema:
Schema::create('countries', function(Blueprint $table)
{
$table->increments('id');
$table->string('code');
$table->timestamps();
});
Schema::create('country_translations', function(Blueprint $table)
{
$table->increments('id');
$table->integer('country_id')->unsigned();
$table->string('name');
$table->string('locale')->index();
$table->unique(['country_id','locale']);
$table->foreign('country_id')->references('id')->on('countries')->onDelete('cascade');
});
Next step is to configure your main Model and also related model for translations:
// models/Country.php
class Country extends Eloquent {
use \Dimsav\Translatable\Translatable;
public $translatedAttributes = ['name'];
protected $fillable = ['code'];
}
// models/CountryTranslation.php
class CountryTranslation extends Eloquent {
public $timestamps = false;
protected $fillable = ['name'];
}
Then you can fill in and use translations, like this:
$data = [
'code' => 'gr',
'en' => ['name' => 'Greece'],
'fr' => ['name' => 'Grèce'],
];
$greece = Country::create($data);
echo $greece->translate('fr')->name; // Grèce
Similar package: spatie/laravel-translatable
10. spatie/laravel-medialibrary: Associate files with Eloquent models
I intentionally left this awesome package the last in the list, because I assume/hope everyone knows it. It has over 1 million downloads overall. But for those who don’t know it…
Here’s how you configure your models to have media.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
class News extends Model implements HasMedia
{
use HasMediaTrait;
...
}
And then you can attach any media files to the model:
$newsItem = News::find(1); $newsItem ->addMedia($pathToFile) ->toMediaCollection();
Finally, here’s how to retrieve those files:
$mediaItems = $newsItem->getMedia(); $publicUrl = $mediaItems[0]->getUrl(); $publicFullUrl = $mediaItems[0]->getFullUrl(); //url including domain
In the database, records are stored in a separate media table which uses Polymorphic Relations.
So, that’s it, TOP 10 hand-picked packages, along with their similar packages. Anything I’ve missed? Any more packages to enhance Eloquent?