Database helpers
DatabaseDriver
DatabaseDriver models the drivers a package may special-case. Postgres is the common odd one out (native ILIKE, functional indexes), so isPgsql() reads cleaner than comparing magic strings at call sites:
| Case | Driver name |
|---|---|
DatabaseDriver::Mariadb | mariadb |
DatabaseDriver::Mysql | mysql |
DatabaseDriver::Pgsql | pgsql |
DatabaseDriver::Sqlite | sqlite |
use Illuminate\Support\Facades\DB;
use RoundlyConsulting\PackageToolkit\Enums\DatabaseDriver;
// Boot / console / migration paths — may fail loudly:
if (DatabaseDriver::current()->isPgsql()) {
// Postgres-only branch
}
DatabaseDriver::current(DB::connection('reporting')); // a specific connection
// Request paths — degrade to the portable branch instead of throwing:
$isPgsql = DatabaseDriver::tryFrom($connection->getDriverName())?->isPgsql() ?? false;current() reads the given connection — or the default one — and throws InvalidConfigurationException for a driver the enum does not model. The set is deliberately closed while Laravel’s is not (sqlsrv is a first-party driver it does not carry), so call current() only on boot, console and migration paths that may fail loudly. On a request path use tryFrom() with a portable fallback, so an unmodelled engine degrades instead of turning a working endpoint into a 500.
whereLikeEscaped()
An injection-safe “contains” match for raw user input that works on every Laravel database driver. Register it with RegistersBlueprintMacros and it is available on the query builder and the Eloquent builder alike:
use Illuminate\Support\Facades\DB;
// ILIKE on Postgres, LIKE on every other driver (sqlsrv included),
// with the user's % _ \ escaped via ESCAPE '\'.
DB::table('comments')->whereLikeEscaped('body', $term)->get(); // query builder
Comment::query()->whereLikeEscaped('body', $term)->get(); // Eloquent builder
// The third argument sets the boolean — combine matches with OR:
Comment::query()
->whereLikeEscaped('title', $term)
->whereLikeEscaped('body', $term, 'or')
->get();
// "%" stays literal: matches "he%lo there", not "hello world"
Comment::query()->whereLikeEscaped('body', '%lo')->get();- User wildcards % and _ (and the escape character \) are escaped, so a search term never widens the match beyond a literal substring. On SQL Server [ is escaped too, because T-SQL reads it as a character class.
- The match uses an explicit ESCAPE '\' clause on every driver — SQLite has no default escape character, so a plain LIKE would leave escaped wildcards live.
- Postgres uses ILIKE; every other driver, sqlsrv included, uses LIKE. The macro never throws for a driver the DatabaseDriver enum does not model — it takes the portable LIKE branch.
- Case-insensitivity comes from ILIKE on Postgres; elsewhere it follows the engine — SQLite’s LIKE folds ASCII only, and MySQL, MariaDB and SQL Server follow the column’s collation (their default collations are case-insensitive).
- The column is developer-supplied and wrapped by the grammar; the needle and the escape character are bound — no user input ever reaches an identifier position.
Without the macros
The same logic is available directly: LikeSearch::apply() adds the clause to any query builder, and LikeEscaper::escape() escapes a term for a hand-written clause — always pair it with an explicit ESCAPE clause:
use Illuminate\Support\Facades\DB;
use RoundlyConsulting\PackageToolkit\Support\LikeEscaper;
use RoundlyConsulting\PackageToolkit\Support\LikeSearch;
// The same clause the macro adds, on any query builder:
LikeSearch::apply(DB::table('comments'), 'body', $term);
// Escape a term yourself (\, % and _) — always pair it with an explicit ESCAPE:
$needle = '%'.LikeEscaper::escape($term).'%';
DB::table('comments')->whereRaw('body like ? escape ?', [$needle, '\\']);Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.