zing/laravel-eloquent-extensions
Install with Composer:
composer require zingimmick/laravel-eloquent-extensions
The package is a plain Eloquent add-on — no service provider to register by hand (Laravel's package discovery handles it), no migrations, no config file to publish in most cases. If the version you pull ships a config file, php artisan vendor:publish --tag=... will surface it, but nothing is required for the common path.
Where to look first, in this order:
vendor/zingimmick/laravel-eloquent-extensions/README.md — the canonical list of what each trait/macro does.vendor/zingimmick/laravel-eloquent-extensions/src/ — small package; the concerns/builders you can use are all here.vendor/zingimmick/laravel-eloquent-extensions/tests/ — the fastest way to see intended usage; every trait has an executable example.A good first use case: pick your most bloated model, find the extension that matches behaviour you've been copy-pasting between models (reusable scopes, builder helpers, model concerns), and replace the duplication with the trait. That gives you an immediate read on whether the package earns its place in your dependency list before you roll it out everywhere.
On 3.5.0 specifically: this is a compatibility release. It adds Laravel 13, PHP 8.5, and PHPUnit 12 support, plus the accompanying orchestra/testbench constraint bump. There are no API changes, no deprecations, and no migration steps — if you're already on 3.x, composer update is the whole upgrade.
Trait-on-model is the primary pattern. Add the concern to a model, then use the query helpers it exposes as normal Eloquent calls. Because they resolve through the model's builder, they compose with where, with, paginate, and anything else in your existing chains — you shouldn't need to restructure query code to adopt them.
use Zing\LaravelEloquentExtensions\...; // trait from src/
class Post extends Model
{
use /* trait */;
}
Keep extension usage in scopes, not controllers. If an extension changes what a query returns (ordering, filtering, eager-loading side effects), wrap it in a named local scope on the model. Consumers then read Post::published()->latestActivity() and the extension stays an implementation detail you can swap or remove.
Use a base model as the rollout boundary. Rather than adding traits to thirty models, add them to your App\Models\Model base class once, run the suite, and let inheritance distribute them. This also gives you one file to revert if a trait interacts badly with something.
Gate adoption behind your test suite, on the new toolchain. 3.5.0's headline is platform support, so this is the release where you verify the upgrade path end-to-end:
composer require --dev "phpunit/phpunit:^12" # if moving
php artisan test
If you run PHPUnit 12, remember annotations are gone — convert @test, @dataProvider, and @depends docblocks to #[Test], #[DataProvider], #[Depends] attributes before blaming the package for a red suite.
Pin the constraint at the minor you actually test against. "zingimmick/laravel-eloquent-extensions": "^3.5" keeps you on 3.x while allowing patch fixes. This package ships compatibility releases frequently (3.5.0 contains 20+ dependency bumps alongside the real work), so a loose * will silently drag framework constraints forward.
In package-adjacent code, mirror the maintainer's matrix. If you maintain your own package that depends on this one, copy the orchestra/testbench constraint bump and PHP/Laravel matrix from 3.5.0's composer.json — that's what the release actually validates against.
illuminate/database to 11/12. Check composer why-not before assuming the release changed anything for you.Builder::hasMacro('name') and Builder::getMacro('name') are quick sanity checks.scopeActive, or both hooking boot/booted, will throw or silently shadow. When adding a trait to a base model, grep the codebase for the method names it introduces first.->toSql() with ->getBindings(), or DB::listen() / Laravel Telescope, tells you whether the extension emitted what you expected. Most "the package is broken" reports are an interaction with an existing scope.newEloquentBuilder() for a custom builder, newCollection() if the package's behaviour needs a custom collection, and local scopes for anything you want to keep overridable. Wrapping rather than forking keeps future 3.x bumps trivial.php artisan config:cache in deploy, re-run it after a major bump anyway — stale caches are the usual cause of "it worked locally".src/. When in doubt about a method's exact signature, read the trait — it's a few dozen lines.How can I help you explore Laravel packages today?