protonemedia/laravel-mixins
A collection of handy Laravel mixins that add useful methods to core classes like collections, query builders, requests, and strings, helping you write cleaner, more expressive code with less boilerplate.
composer require protonemedia/laravel-mixins
There is no config file to publish and no migration to run — the service provider is auto-discovered and registers a ::mixin() call for each supported framework class during boot(). The practical "installation" step is really discovery: open vendor/protonemedia/laravel-mixins/src/Mixins/ (and the README method table) once, and note which classes are touched — Str, Collection, Arr, the query/Eloquent Builder, Blueprint, Request, TestResponse, and a few others. Each mixin is a tiny class of public closures, so reading the source is faster than reading docs.
Confirm what actually got registered before you build on it:
php artisan tinker
>>> Illuminate\Database\Query\Builder::hasMacro('whereLike'); // true/false
>>> Illuminate\Support\Str::hasMacro('someMethod'); // verify per class, per version
First use case: reach for the query-builder mixin the next time you write a search endpoint, instead of hand-rolling LIKE concatenation:
// app/Http/Controllers/UserSearchController.php
public function __invoke(Request $request)
{
$term = $request->string('q')->toString();
return User::query()
->whereLike('name', "%{$term}%") // or the equivalent documented helper
->paginate();
}
That single change is representative of the package's value: it replaces small, repeated boilerplate (LIKE clauses, schema shortcuts, test assertions) with chainable, framework-native-looking methods. Treat it as a convenience layer, not an architecture decision — nothing here is load-bearing.
1. Use it inside scopes and query objects, not controllers. The biggest payoff comes when the mixin methods become domain vocabulary:
// app/Models/User.php
public function scopeMatching(Builder $query, string $term): Builder
{
return $query->whereLike('name', "%{$term}%")
->orWhereLike('email', "%{$term}%");
}
Callers now use User::matching($term). If the package is ever abandoned or the method is absorbed into Laravel core, you edit one scope instead of forty call sites.
2. Wrap mixin calls in your own app-level helper when the semantics matter. Anything that touches case sensitivity, collation, or driver behaviour should be renamed. A method called whereLike means different things on MySQL (case-insensitive by default) vs. Postgres (ILIKE is a separate operator). Encapsulating it in scopeMatching gives you a place to swap in whereRaw('LOWER(name) LIKE ?') if you need portable behaviour.
3. Migrations — use the Blueprint mixin for repeated column patterns. If the package ships helpers you use in every migration (index/foreign-key shortcuts, timestamp variants), standardise on them in a project stub so new migrations look consistent. Keep the raw $table->... call nearby in a comment if the helper is non-obvious to a reviewer.
4. Tests — the TestResponse mixin is the highest-leverage, lowest-risk area. Assertion helpers only affect test code, so a breaking change shows up as a red test rather than a production bug. Adopt these first; be conservative with anything the package mixes into Request or the query builder.
5. Chain mixins with native methods freely — they're real macros, so Str::of($x)->..., collect(...)->..., and Model::query()->... all behave normally. There's no wrapper object, no proxy, no extra allocation.
6. Centralise your own macros the same way. If you add project macros, put them in a dedicated MacrosServiceProvider using Str::mixin(new AppStrMixin) and mirror the package's structure. It keeps macro registration discoverable and stops AppServiceProvider::boot() from becoming a dumping ground.
composer update. Before every major Laravel bump, grep your code for the mixin method names and check the upgrade guide / Illuminate\... source for a native equivalent. Add a test that pins the expected behaviour of each mixin method you depend on.@method docblocks on a local stub (or Laravel Idea), and prefer wrapping calls in named scopes so most of your codebase calls your method, not the magic one.hasMacro() is your debugger. If a call vanishes or throws BadMethodCallException, run Builder::hasMacro('x') / Str::hasMacro('x') in tinker. It tells you instantly whether the package version you installed actually ships that method — the README on main may be ahead of your locked version.Macroable has no conflict detection; last registration wins. If you use other macro packages, register yours explicitly in a service provider and test the interaction — don't rely on discovery order.boot() runs once, so a macro registered only for certain requests leaks into later ones. Keep macro registration unconditional; put conditional logic inside your own wrappers.Blueprint/grammar mixins are the most version- and driver-fragile part of the package. Schema internals change between Laravel majors and differ per DB driver. If you use them, run migrations against every driver you support (SQLite in tests, MySQL/Postgres in CI) — SQLite tolerance hides a lot.MacrosServiceProvider (they're ~20-line classes, MIT licensed) and you eliminate the dependency entirely while keeping the syntax."protonemedia/laravel-mixins": "^3.0") and read the changelog on update. Macro packages have no deprecation path — methods are added and removed between minors.How can I help you explore Laravel packages today?