garetjax/phpbrowscap
PHP Browscap provides fast, accurate browser and user-agent detection for PHP applications. It parses browscap data to identify browser, platform, device, and crawler details, with caching support for production performance.
Architecture fit. garetjax/phpbrowscap is a standalone, framework-agnostic PHP library that replaces PHP's native get_browser() by parsing a browscap.ini capability database and returning structured client metadata (browser, version, platform, device flags, crawler flag). For a Laravel product it belongs in the request-enrichment layer: middleware that decorates the request, analytics and log enrichment, compatibility/legacy-browser messaging, device-class routing, and conservative bot tagging. It has zero coupling to Laravel, which is good for lock-in and bad for glue: we own the service provider, config, cache bridge, and the ini refresh lifecycle.
Integration feasibility. Composer-installable and small in surface area, but not turnkey. The real work is an in-house adapter: a BrowserDetector contract bound as a singleton, a config file for ini path and cache strategy, a scheduled refresh command with atomic swap, and per-user-agent caching. The critical feasibility gate is whether the package's legacy-era code and Composer constraints survive the target PHP runtime — a short POC is mandatory before committing.
Technical risk. Moderate, and mostly not about code quality:
Dependents: 0), and the actively maintained successor is browscap/browscap-php with the same underlying data model. This package is best treated as a reference implementation, not a platform dependency.Key questions.
jenssegers/agent, matomo/device-detector) already in the stack?Stack fit. Laravel 8–11 via Composer, behind a thin adapter: bind the package's browser class as a singleton, back its cache with the app's cache store (Redis in production), publish the ini into storage/app/browscap, and expose a BrowserDetector interface so application code never imports the package namespace. That interface is the insurance policy that makes swapping to the maintained successor a contained, non-breaking change.
Migration path. Do not rip out existing get_browser() calls or an incumbent agent library directly. Introduce the interface, implement it against this package, and run shadow mode against a sampled corpus of real User-Agent strings, diffing output against the incumbent. Promote one consumer at a time — logging/analytics first, then bot tagging, then any user-facing compatibility or feature gating. Roll back per consumer, not per deployment.
Compatibility. The primary gate is the PHP runtime matrix; secondary is the cache adapter contract, which predates PSR-6/PSR-16 and needs a bridge to Laravel's cache. The browscap.ini format itself is stable, so data compatibility is not the concern — our POC carries the burden of proof on runtime and integration.
Sequencing.
browscap:update scheduled command with checksum and atomic swap.Maintenance. The package code is effectively frozen; we inherit ownership of any fixes. Ongoing cost is dominated by the ini lifecycle, not the code: scheduled download, integrity verification, atomic replacement, and a rollback slot for bad upstream releases. Budget a modest recurring line item and name a documented owner — without one, detection accuracy silently decays and no one notices until a feature misfires.
Support. Community support is thin, so escalation is effectively internal. Document the adapter, the ini refresh runbook, and the successor library as the intended escape hatch in the platform team's ownership wiki. Support volume is low but non-zero, and it lands on whoever owns the adapter.
Scaling. Warm-cache reads are cheap and horizontally scalable through shared Redis. The constraints are (a) each node or image needs the ini present, which complicates immutable builds and serverless cold starts, and (b) cold-cache parse is heavy, with the full ini as the main offender. Mitigations: ship the lite ini in the image, pre-warm the cache via a deploy job, and use a per-request fallback so a cache miss never blocks on a full parse. Per-UA memoization is the largest practical performance win and should be the default, not an optimization.
Failure modes.
BrowserDetector contract needs a null-object implementation so consumers degrade gracefully.Ramp-up. A mid-level Laravel engineer can deliver the provider, cache bridge, and refresh command in roughly one sprint. The expensive part is validation, not code: building the UA fixture corpus, running shadow mode, and agreeing on refresh and rollback policy. Plan two sprints end to end — one to build, one for parity and cutover — and treat the "swap to the maintained successor" decision as a scheduled checkpoint rather than a launch-time afterthought. Recommendation to stakeholders: run a time-boxed pilot on one non-critical consumer, adopt only if accuracy, maintenance posture, and update cadence clear the bar, and keep the adapter boundary regardless so the parser remains a commodity we can replace.
How can I help you explore Laravel packages today?