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

Placeholder Resolver Laravel Package

dflydev/placeholder-resolver

A lightweight PHP library for resolving placeholders such as %key% in strings using array or custom data sources. It supports recursive substitution, nested lookups, and circular-reference detection, making it useful for configuration and templating.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. dflydev/placeholder-resolver is a small, framework-agnostic Composer library whose entire job is: given a placeholder token (e.g. ${foo.bar}) and a pluggable DataSourceInterface, return the resolved value — recursively, so a value may itself contain placeholders. It has no opinion about Laravel, no service provider, no facade, no config integration. That is both its strength (nothing to fight) and its weakness (everything Laravel-specific is our code). The natural Laravel use cases are narrow and infrastructural: resolving cross-referencing config values, layering environment/tenant overrides onto a base config tree, and parameter substitution in YAML/JSON config files loaded by a custom loader. It is not a templating engine for user-facing output — Blade already owns that space and this library would be a regression there.

Integration feasibility. High in the mechanical sense: composer require, one container binding for the data source, one singleton for the resolver. Expected effort is a one-to-two-day spike plus a thin (~100 LOC) Laravel wrapper. The real question is whether we need the library at all — a placeholder resolver with cycle protection is roughly 50 lines of our own code, and we would own the semantics outright. With 141 stars, zero visible dependents, and an opportunity score of ~31, this reads as a commodity capability rather than an ecosystem bet. I would fund a spike, not a commitment.

Technical risk. Three items dominate:

  • Maintenance posture. Low-activity upstream, likely older PHP version constraints, no typed interfaces or PHP 8 idioms guaranteed. If it declares php: >=5.3 we are fine, but if it caps below our runtime we are pinned on a library nobody is patching.
  • Recursion semantics. Recursive resolution is the value-add and the primary failure surface. We must confirm cycle detection, depth limits, and whether unresolved placeholders throw, return the literal token, or return null. That behaviour becomes our contract whether we like it or not.
  • Secret exposure. If the DataSource is wired to env()/config, any code path that renders a resolved value into logs, exception traces, or an API response turns this into a credential-leak vector.

Key questions for the spike.

  1. What PHP versions and dependency constraints does the current tagged release declare?
  2. Is the placeholder regex configurable, and does it support escaping a literal ${ in content?
  3. How are circular references handled — exception, or hang? Is there a bounded depth?
  4. Are unresolved placeholders surfaced as exceptions or silently passed through? (We need the former.)
  5. Is there a maintained fork or a first-party equivalent (symfony/dependency-injection ParameterBag, Twig, or Laravel's own config repository extension) that already covers 90% of our need?

Integration Approach

Stack fit. Clean fit only if we keep the library at the configuration layer. Bind a DataSourceInterface implementation backed by config() (and optionally a curated env allow-list), register the resolver as a singleton, and expose one small service — PlaceholderService::resolve(string $value): string — that the rest of the app depends on. Do not let controller or view code import Dflydev\ namespaces directly; the wrapper is our seam if we later replace the library with in-house code.

Migration path. Start by inventorying existing ad-hoc interpolation — str_replace chains, preg_replace_callback in config loaders, custom %param% handling in YAML bootstrappers. Each of those is a candidate to consolidate behind the new service. Migrate config-file resolution first (low blast radius, easy to diff), then any runtime string interpolation, and only then consider tenant/feature-flag overrides. Leave Blade templates untouched.

Compatibility. Verify against our actual PHP matrix and Laravel version before writing code — this is a gate, not a task. Add a contract test suite that exercises the resolver through our wrapper only, so an upstream swap is a single-file change. If the upstream constraint blocks our PHP 8.2/8.3 runtime, fork-and-vendor is acceptable for a library this small; patching 200 lines is cheaper than abandoning a config standard mid-migration.

Sequencing.

  1. Spike (1–2 days): answer the five questions, confirm PHP matrix, prototype the wrapper, write the cycle/depth/unresolved tests.
  2. Decision gate: adopt vs. build in-house (~50 LOC) vs. use an existing first-party component. Publish the comparison, not just the recommendation.
  3. Wrapper + service provider, shipped behind a feature flag, used only by the config loader.
  4. Migrate one real consumer and measure; then generalise.
  5. Document the placeholder contract (syntax, escaping, error behaviour) in the platform docs before any second team adopts it.

Operational Impact

Maintenance. Upstream maintenance is not something we can rely on; assume we own this. Budget for a fork-and-vendor contingency and pin the version exactly — no caret ranges on a library with this activity profile. The wrapper keeps the long-term maintenance surface at roughly one file plus a test suite.

Support. No vendor support, community issues only. Internal ownership must be assigned to the platform team explicitly, with the wrapper documented as a platform primitive. Without a named owner this becomes orphaned infrastructure that a future team is afraid to remove.

Scaling. Resolution cost is trivial at typical config volumes (tens to low hundreds of values) and can be cached at boot. The scaling concern is not throughput, it is cardinality: if placeholders are resolved per-request against a large data source, or if resolution is ever applied to user-supplied strings, cost and risk both change shape. Constrain it to boot-time and config-time resolution and the scaling question disappears.

Failure modes to instrument.

  • Circular reference → hang or uncaught exception at boot. Mitigate with an explicit depth cap and a startup self-test of the config graph.
  • Unresolved placeholder → literal ${foo} leaking into a rendered value or, worse, into a query. Fail loud at boot.
  • Secret leakage → resolved secrets in logs, exception traces, or /config debug endpoints. Redact resolved values in the resolver's __toString/logging path.
  • Silent semantics drift → upgrade changes throw-vs-passthrough behaviour and nothing tests for it. Covered by the contract suite.
  • Regex backtracking on unusually long config strings — low probability, worth one boundary test.

Ramp-up. Low. The API surface is small enough that any mid-level Laravel developer is productive in under an hour once the wrapper and the written placeholder contract exist. The ramp-up risk sits with consumers, not authors: teams must know the difference between config-layer placeholders and Blade templating, or we will end up with two interpolation dialects in one codebase. Address that in the docs step, not after adoption.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings