Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Support Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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.

Implementation Patterns

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.

Gotchas and Tips

  • Everything is static. 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.
  • The GeoIP database is not shipped. You must supply your own 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.
  • Method names drift between this package and its consumers. 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.
  • Low bus factor. One maintainer, 58 stars, last release 2024-05. Pin it ("pragmarx/support": "^x.y") and keep it behind wrappers (above). The BSD-3-Clause license is commercially fine; the risk is maintenance, not legal.
  • Debugging is trivial — lean on it. 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.
  • Check the PHP constraint before upgrading PHP. These support packages were written across a wide PHP range; if you're on 8.3+ and hitting deprecations from dynamic properties or implicit nullable params, it's this package, not your app.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource