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

Uri Template Laravel Package

guzzlehttp/uri-template

Expands RFC 6570 URI templates into concrete URI strings in PHP, turning templates like /users/{id}{?tab} into real paths with query strings from an array of values.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Single-purpose, stateless, dependency-free utility. UriTemplate::expand() is a pure static function: template string + variable array in, URI string out. There is no service provider, no config surface, no I/O, no state to manage. In a Laravel codebase it belongs in the integration/adapter layer, not the domain layer — the natural consumers are third-party API clients, HATEOAS/hypermedia consumers (HAL, JSON:API, Siren), pagination-link followers, and OAuth/OIDC discovery metadata resolvers, all of which publish links as RFC 6570 templates (/users/{id}{?tab}, {/id}{?page,per_page}, {+base}assets{/path}). If we are not consuming templated links from an external contract, this package adds nothing — naive string interpolation is sufficient and cheaper.

Integration feasibility. composer require guzzlehttp/uri-template and done; no bootstrapping, no migration, no configuration. The real integration question is not "can we install it" but "do we already have it": Guzzle 7 depends on guzzlehttp/uri-template transitively, so most Laravel apps already ship it. The work is therefore governance — pinning a constraint deliberately and potentially upgrading v1 → v2 — rather than greenfield adoption.

Technical risk. Low, with three specific caveats:

  • Transitive presence invalidates the popularity signal. The Dependents: 0 and 198-star figures understate reality; this is a carve-out of a class that lived inside Guzzle itself and is pulled in by Guzzle 7. The composite score of ~22.7 is an artifact of the scoring model, not a signal about the package. Recommend we do not let the score drive the decision.
  • v2.0.0 is a behavioral break, not a cosmetic one. Invalid template syntax now throws InvalidArgumentException instead of expanding partially; invalid UTF-8, non-finite floats, and malformed literals now throw; unsupported shapes no longer degrade to warnings or Array output. Any code currently passing loosely-typed data (nulls, floats, mixed arrays, Stringable objects) may start throwing in production where it previously produced a slightly-wrong URL.
  • PHP upper bound. The README guidance table states v2.0 supports >=7.4,<8.6, while the v2.0.1 release notes claim PHP 8.6 support. That inconsistency needs resolving before we commit, because an upper bound below our platform's next PHP upgrade becomes a forced-upgrade trigger mid-cycle.

Key questions.

  1. Which of our integrations actually receive RFC 6570 templates, and do we need reserved ({+var}) or fragment ({#var}) expansion — or only the simple/query/path operators?
  2. Who authors the templates — us (trusted, at build time) or a third party (untrusted, at runtime)? This determines whether we need post-expansion host/protocol allow-listing.
  3. Are we currently on Guzzle's v1.x transitively, and does anything depend on the old lenient expansion behavior?
  4. What is our PHP upgrade calendar relative to the <8.6 bound?
  5. Is Tidelift-backed commercial support a procurement requirement for security-sensitive dependencies, or is MIT + community maintenance acceptable at our risk tier?

Integration Approach

Stack fit. Laravel 10/11/12 on PHP 8.2–8.5 all satisfy the constraint. No container bindings are strictly required, but I would still wrap it: a thin UriTemplateExpander service (or a HypermediaLink value object factory) that owns the expand() call, normalizes/validates the variable array, and converts InvalidArgumentException into a domain-meaningful failure. That wrapper is where we add the security validation described below and where we can swap implementations if the package ever stalls.

Migration path.

  1. Run composer why guzzlehttp/uri-template to establish whether we already have it transitively and at which major.
  2. If v1.x is present transitively, decide explicitly: pin to ^1.0 (stay lenient, low effort) or move to ^2.0 (strict, better correctness, requires auditing call sites). Prefer ^2.0 on new code; treat existing call sites as a separate, tested upgrade.
  3. Audit every call site for inputs that v2 now rejects: partial/invalid templates, invalid UTF-8, INF/NAN, deeply nested nulls, sparse arrays, and objects with side-effecting __toString().
  4. Confirm nothing instantiates UriTemplate or serializes it — v2 makes it non-instantiable and non-serializable, which breaks any queued-job or container-singleton usage.

Compatibility. Composer platform config and CI matrix must be checked against the <8.6 ceiling; if 2.0.1 does grant 8.6, pin ^2.0.1 rather than ^2.0 so the constraint resolves. No Laravel-version-specific concerns; nothing touches the framework. Note that v2 changed map/list discrimination (dense zero-indexed arrays → lists, sparse/mixed → maps) — payloads built with array_filter or keyed by IDs will silently change expansion, so add fixture-based tests around our real query-building code.

Sequencing. (1) Discovery/audit of template-producing integrations. (2) Constraint decision + lockfile change. (3) Wrapper service + validation + unit tests, merged before any consumer uses it. (4) Pilot on a single low-blast-radius integration (e.g. pagination-link following in a background sync job). (5) Roll out consumer by consumer. (6) Document the input contract in our internal conventions doc so future teams don't hand-roll expansion.

Operational Impact

Maintenance. Effectively zero ongoing cost: no config, no scheduled tasks, no storage, no framework coupling. The release history shows a healthy cadence (v1.0.6 → v1.0.10 plus v2.0.0 and v2.0.1, spanning 2025–2026), but the content is almost entirely edge-case correctness fixes — Unicode prefix-modifier counting, pct-encoding preservation, float locale separators, PCRE failure reporting. That pattern tells us the surface is small and being hardened, not feature-churning. Budget a changelog review per Dependabot PR; patch bumps are low-risk, minor bumps on 1.x have historically carried bug fixes only, and any 2.x minor should be read carefully for input-contract tightening.

Support. MIT, maintained by the Guzzle organization, security reports routed to [email protected]. The Tidelift Subscription is available if we need a commercial support agreement or a security-response SLA to clear vendor risk review — that is the pragmatic lever here, and it is one of the few OSS utilities where the option exists at all.

Scaling. Non-issue. Pure in-process string manipulation, microsecond-scale, no allocations that matter, no external calls, safe in Octane and under high concurrency because there is no shared state. If we expand the same template with the same values repeatedly (e.g. per-request link generation), memoize at the wrapper level — but measure first; this will never be the bottleneck.

Failure modes.

  • Throwing on bad data. A malformed template or an invalid-UTF-8 / non-finite-float / non-stringable value in a third-party response now raises InvalidArgumentException at runtime. Every call site needs a try/catch and a defined fallback (skip the link, log at warning, alert if it's a critical path). This is the most likely production incident from the upgrade.
  • Silent semantic drift. Undefined/null variables are omitted rather than rendered; booleans become 1/0 at every nesting level; sparse arrays become maps. URLs will be valid but wrong. Only fixture tests catch this.
  • Security — untrusted templates. If template text arrives from a remote service, expansion can produce an attacker-influenced absolute URL ({+next} → //evil.example). Treat the expanded result as untrusted: re-parse it, allow-list scheme and host, and drop anything that escapes the expected base origin before handing it to an HTTP client. This is an SSRF/open-redirect control, not a library concern, and it is the single most important thing to get right if templates come from outside our codebase.
  • Double encoding. Values that are already pct-encoded interact with reserved/fragment expansion in non-obvious ways (several v1.0.6/v2.0.0 fixes target exactly this). Pass raw values, not pre-encoded ones, and test with values containing %2F, spaces, and non-ASCII.

Ramp-up. Hours, not days. One static method, a one-page quick start, a usage doc, and an input-contract doc. The only genuine learning investment is RFC 6570 operators ({?}, {&}, {#}, {+}, {/}, {.}, {;}), explode (*), and prefix (:n) semantics — roughly half a day for an engineer to become confident, and worth capturing as a short internal note plus a shared test fixture set so the knowledge does not sit with one person.

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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table