ablunier/laravel-database
ablunier/laravel-database provides convenient database helpers for Laravel applications, simplifying connection management, schema operations, and common queries. Keep persistence logic clean and consistent with a lightweight package that integrates smoothly into your existing Laravel workflows.
Before you install, do a compatibility read. ablunier/laravel-database was last released 2017-05-23, which puts it in the Laravel 5.4/5.5 era. With 1 star, 0 dependents and no recent activity, treat it as source you are adopting, not as a maintained dependency. Check the composer constraint first:
composer show ablunier/laravel-database --all # see requires: php, illuminate/*
If your app is on Laravel 8+ / PHP 8+, plan on forking rather than pulling the tagged release — see Gotchas.
Install (if constraints allow):
composer require ablunier/laravel-database
Then check whether it self-registers:
grep -A5 '"extra"' vendor/ablunier/laravel-database/composer.json
extra.laravel.providers is present → auto-discovered, nothing to do.config/app.php under providers manually. This is the single most common reason the package "does nothing": no discovery, no registration, no macros.Where to look first. The package is small; read it end-to-end in ten minutes instead of guessing from the README:
vendor/ablunier/laravel-database/src/*ServiceProvider.php — this tells you everything. Look for macro(, mixin(, bind(, singleton(, commands([, and $this->publishes(.vendor/ablunier/laravel-database/config/ (or src/config/) — if there's a config file, publish it: php artisan vendor:publish --provider="Ablunier\...\ServiceProvider".composer.json → require block — confirms which Illuminate components it actually touches (usually illuminate/database, illuminate/support).First use case. Utilities packages of this vintage are almost always macro packs — helpers hung off Illuminate\Database\Query\Builder or Illuminate\Database\Eloquent\Builder. Find them fast:
grep -rn "macro(" vendor/ablunier/laravel-database/src
php artisan tinker
>>> DB::table('users')-><macroName>(...)
Pick the one macro that maps to a query you write repeatedly (soft-delete-aware counts, whereLike, upsert helpers, raw-expression wrappers). Verify it emits the SQL you expect via ->toSql() before you refactor anything to use it.
Wrap it, don't sprinkle it. Because the upstream is dormant, isolate every call site behind your own boundary so a future swap is a find-and-replace in one file:
// app/Support/Db.php
final class Db
{
public static function activeUsers(): \Illuminate\Database\Query\Builder
{
return DB::table('users')->whereActive(); // package macro lives here only
}
}
Verify registration order in the provider. If the package registers macros in boot(), they are global — every DB::table() and every Eloquent builder in the app inherits them. Confirm this is what you want; a global Builder macro that silently rewrites where clauses is a blast radius, not a feature.
Test the macro, not the package. Since the package ships no meaningful test suite you can rely on, pin behaviour with a test that asserts the generated SQL:
public function test_active_scope_sql(): void
{
$sql = User::query()->whereActive()->toSql();
$this->assertSame('select * from "users" where "active" = ?', $sql);
}
That test is also your upgrade tripwire: it fails loudly the day a Laravel bump breaks the macro's assumptions.
Use it for read paths first, not schema. Utilities that decorate query builders are cheap to adopt and cheap to abandon. Anything that touches Blueprint (column types, index helpers) belongs in migrations you intend to keep forever — if the package provides schema helpers, run php artisan migrate --pretend once, then inline the resulting core Blueprint calls into your migration and drop the dependency from that file.
Console commands / scheduled jobs. If the provider registers commands (commands([...]) in register() or boot()), they appear in php artisan list. Anything that looks like a cleanup/prune job should go into app/Console/Kernel.php explicitly rather than relying on the package's own scheduling.
Observability integration. These helpers compose naturally with DB::listen() for local profiling, and with Model::preventLazyLoading()-era debugging — register the listener after the provider boots so you capture the utility-generated queries too.
Fork-and-pin as the real integration path. Given zero dependents, the durable pattern is: fork to your org, tag 1.0.0-yourorg, require via a VCS repository, and treat the fork as first-party code you own. That converts "abandoned package" into "vendored utility" without changing any call sites.
Laravel version drift is the primary risk. 2017-era providers commonly use $defer = true (removed in 5.8), type-hint Illuminate\Database\Query\Builder in ways that break against newer grammars, or rely on Str/Arr helpers that were reorganized. Symptom: BindingResolutionException, Call to undefined method, or a macro that exists but throws on invocation. Fix by copying src/ into app/Support/Database/ and adjusting — you are unlikely to get upstream patches.
PHP 8 landmines. Expect each() (removed 8.0), implicit nullable parameter deprecations, count() on non-countable, and missing return types that only warn. Run php -l and the test suite under your target PHP before committing to the dependency.
Silent no-op registration. If there's no extra.laravel.providers, forgetting the manual config/app.php entry gives you zero errors — just Method ... does not exist at the first call. Always confirm registration explicitly:
php artisan tinker
>>> app()->getProvider(\Ablunier\...\ServiceProvider::class)
Macro collisions don't fail loudly. Macroable::macro() overwrites. If another package (or your own code) defines the same macro name, the last provider to boot wins. Pin the order in config/app.php and grep the codebase for the macro name before adopting it.
Config caching. If you publish and edit a config file, php artisan config:cache will happily serve stale values in production — php artisan config:clear is the first debugging step whenever behaviour differs between local and production.
Debugging queries generated by helpers. ->toSql() and ->getBindings() are your friends; for runtime inspection use:
DB::listen(fn ($q) => logger($q->sql, $q->bindings));
Watch the connection resolver. Utilities that stash a connection or grammar instance at boot can misbehave with multiple connections (mysql + mysql-read) or in tests where RefreshDatabase swaps the connection. Test one macro against a non-default connection early.
Extension points, in order of preference: (1) publish/override any config; (2) override the provider's binding in your own AppServiceProvider with a subclass; (3) fork. There is no plugin surface here — the provider is the extension point.
Bottom line for day-to-day use: adopt only the one or two query-builder helpers that remove real repetition, wrap them behind a single class, assert their SQL in a test, and keep the option of deleting the package in an afternoon. Do not build schema or migration logic on top of it.
How can I help you explore Laravel packages today?