pragmarx/support
pragmarx/support is a Laravel utility package packed with handy helpers: collection macros, string and array utilities, a message bag, router and UUID helpers. It cuts boilerplate and speeds up everyday development in Laravel applications.
composer require pragmarx/support
This is a "utility belt" package: a grab-bag of small, mostly static helper classes that the maintainer's other packages (tracker, google2fa, countries, ci) pull in transitively. There is nothing to publish, no migrations, and — outside of a thin src/Laravel/ folder — no framework coupling. If composer.json declares a provider under extra.laravel.providers, Laravel will auto-register it; otherwise there is literally nothing to configure before first use.
Where to look first: vendor/pragmarx/support/src/. Each subfolder (Config, Filesystem, Uuid, GeoIp, Process, Serializer, Environment, …) is a single self-contained class you can read in two minutes. Read the class you intend to use before you call it — the docblocks are sparse and the README is minimal, but the source is small enough to be the real documentation.
First use case — replace hand-rolled file + ID helpers in a non-Eloquent job:
use PragmaRX\Support\Uuid;
use PragmaRX\Support\Filesystem;
$id = Uuid::make(); // ramsey/uuid v4, as a string
$path = storage_path("app/reports/{$id}.json");
Filesystem::write($path, json_encode($report));
$back = json_decode(Filesystem::get($path), true);
Filesystem mirrors Laravel's File facade (write, get, exists, delete, makeDirectory, deleteDirectory, isDirectory) but is callable outside a Laravel container — which is the whole point of this package. Same story for Uuid and Config: they exist so standalone scripts and package bootstrapping don't need app().
Secondary first use cases, in rough order of day-to-day payoff:
Config::load() for CLI/cron scripts that need .php config files without booting the framework.GeoIp for IP → country/city enrichment when you already have a MaxMind database.Process as a thin wrapper around Symfony Process for shelling out from queue jobs.Config bootstrapping for framework-less entry points. The Config class loads every *.php file in a directory and roots the resulting array at the filename (so config/database.php returning ['host' => …] is read as database.host). Use it at the top of an artisan-less script:
use PragmaRX\Support\Config;
Config::load(__DIR__.'/config'); // done once, before anything else
$host = Config::get('database.connections.mysql.host', '127.0.0.1');
Config::set('database.connections.mysql.host', 'db.internal'); // overrides for this process only
GeoIP enrichment pipeline. Wrap the lookup in a small service and cache results by IP, because MaxMind lookups are file seeks and a busy request table will hammer the DB file:
use PragmaRX\Support\GeoIp\GeoIp;
$geo = new GeoIp(config('services.maxmind.path')); // path to GeoLite2-City.mmdb
$country = $geo->getCountry($request->ip());
$city = $geo->getCity($request->ip());
Cache::rememberForever("geo:{$ip}", fn () => [
'country' => $geo->getCountry($ip),
'city' => $geo->getCity($ip),
]);
Bind this into the container as a singleton rather than constructing per call — the constructor opens the mmdb reader.
Adapter layer, not direct calls. Because every helper is static, the cleanest integration is to wrap what you actually use behind your own interface. You get mockability (statics are untestable in isolation), and if the package is abandoned you swap one thin class instead of grepping for PragmaRX\Support\ across the codebase:
final class ReportStorage
{
public function put(string $name, string $body): string
{
$path = "reports/{$name}.json";
Filesystem::write(storage_path("app/{$path}"), $body);
return $path;
}
}
Subclass when the package is designed for it. GeoIp and Config are non-final and are extended by the maintainer's own packages (tracker subclasses both). If you need different return shapes or an extra config source, extend rather than fork — that's the intended extension point.
Use it as a version-safe floor for transitively required packages. If you're installing pragmarx/tracker or pragmarx/countries, this package is already in your tree. Nothing stops you from reaching for its helpers directly instead of adding a second library for UUIDs or file writes.
Config::set() mutates process-global state; a value set in one test leaks into the next. Reset in tearDown() (Config::load() again on a fixture dir) or avoid set() entirely.Config root keys come from filenames. Two config dirs merged together will silently collide on the same filename. Load order matters — the later load() wins. This is the #1 source of "why is my config wrong" reports.GeoLite2-*.mmdb and keep it updated; the package only provides the reader wrapper. Missing/invalid path errors surface from the underlying geoip2/geoip2 reader, not from clean guard clauses. If geoip2 is only a require-dev dependency in your install, composer require geoip2/geoip2 explicitly.Uuid defers to ramsey/uuid. If your app (or Laravel) pins a different major, Composer resolves the intersection — check composer show ramsey/uuid rather than assuming Uuid::make() returns what you expect. It returns a string, not a UuidInterface.Filesystem bypasses Laravel's Storage. No disks, no S3, no visibility/ACL handling, no file locking, and relative paths resolve against the current working directory, not base_path(). For anything cloud-backed or concurrency-sensitive, use Storage/File instead. This helper is for local scratch and standalone scripts.pragmarx/tracker subclasses GeoIp and adds/renames accessors. Before wiring a call, open src/GeoIp/GeoIp.php in the installed vendor copy — don't copy snippets from a blog post about tracker."pragmarx/support": "^x.y") and keep it behind wrappers (above). The BSD-3-Clause license is commercially fine; the risk is maintenance, not legal.dd(Config::get('…')) or a var_dump inside src/Filesystem/Filesystem.php behaves exactly as you'd hope because there is no magic, no macros, and no deferred resolution. Don't spend time on stack traces; read the 40-line class.How can I help you explore Laravel packages today?