Top 10 Packages to Get More from Laravel Eloquent
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?