codifico/parameter-bag-extension
A lightweight Laravel/PHP extension for the Codifico parameter bag, adding convenient helpers to store, retrieve, merge, and organize application parameters. Keep configuration values tidy and accessible through a simple, fluent API.
Install alongside Behat. This is a Behat extension, so it presumes a working behat/behat setup (composer require --dev behat/behat). Then add the package:
composer require --dev codifico/parameter-bag-extension
Find the extension class first. Since the README is thin and there are ~7 stars / 0 dependents, don't trust blog posts — open vendor/codifico/parameter-bag-extension/ and locate the class implementing Behat\Testwork\ServiceContainer\Extension (likely Codifico\ParameterBagExtension\Extension or similar). That gives you the real config key and namespace before you wire anything up.
Register it in behat.yml. Behat extensions go under extensions: in the profile. The key must match the extension's getConfigKey():
default:
extensions:
Codifico\ParameterBagExtension\Extension:
parameters:
base_url: 'http://localhost:8080'
admin_user: 'qa-admin'
Run vendor/bin/behat --config behat.yml --dry-run to confirm it loads without a config error — this is your fastest signal that the key is wrong.
First real use case. The core value of a ParameterBag over plain config is placeholder resolution (%base_url%). Start by putting a base URL and a test user into the extension config, then reference them in a step or feature to prove the wiring works before you build more on top. This is the smallest loop that exercises the whole chain: config → bag → resolution → step.
Centralize environment-specific values. The whole point of a ParameterBag is to keep volatile values (URLs, credentials, tenant IDs) out of step definitions. Keep behat.yml parameter-free and lean on behat.yml.dist + a local override, or Behat's imports: to layer environment files. Example structure:
imports:
- behat.parameters.yml # gitignored, holds secrets
default:
extensions:
Codifico\ParameterBagExtension\Extension:
parameters:
base_url: '%env(BASE_URL)%'
Note: %env()% resolution depends on how the extension populates the bag — verify in the source whether it delegates to Symfony's ParameterBag::resolveValue (which does not read env vars) or has its own resolver. If it's the plain Symfony bag, %env()% will fail; drop the syntax and use literal values or a config loader.
Consume parameters from a Context. Two likely integration shapes — inspect the source and pick the one it implements:
use ParameterBagTrait;) that Behat's Context can adopt so $this->parameterBag->get('base_url') works inside step definitions.BeforeScenario subscriber / service injected into context via Behat's extension container.If neither exists and the extension only sets up the bag, add a thin Context base class that reads the bag in __construct and exposes helpers to all your contexts. Don't scatter %param% parsing across step definitions.
Use it with Behat Transforms for argument resolution. If the extension resolves placeholders in step arguments, a transform is the natural companion:
/**
* @Transform :url
*/
public function castUrl(string $url): string
{
return $this->parameterBag->resolveString($url);
}
This keeps step definitions clean — Given I visit :url where :url is %base_url%/login resolves in one place.
Layer by suite/profile. Behat profiles (api, ui, ci) can each override parameters. Keep the parameter set identical across profiles and only vary values — otherwise tests become profile-dependent and flaky in CI. This is the standard pattern for a ParameterBag extension and is worth enforcing with a code review check.
Feed the bag from an external source. If the extension supports a custom loader or you can bind a provider, wire parameters to a fixture JSON or .env reader. This is where the package typically pays for itself on teams that already maintain parameters.yml for Symfony apps — reuse the same file so app config and test config don't drift.
Verify the maintenance posture before depending on it. 7 stars, 0 dependents, score 0.185 — this is essentially an unmaintained internal package released to Packagist. Pin the version ("codifico/parameter-bag-extension": "1.*") and plan for a fork if Behat bumps a major version. Check composer.json's require/require-dev for the Behat version it was tested against; Behat extension APIs have shifted between 3.x minors.
Extension config key mismatch is the #1 failure. Behat throws a cryptic "Unrecognized option" or silently ignores the block if the FQCN in behat.yml doesn't match getConfigKey(). Always var_dump the extension's configure() in a scratch copy if the config isn't taking effect.
Clear Behat's cache when changing parameters. Behat caches the container; if a parameter doesn't seem to update after editing behat.yml, run with --no-cache or delete var/cache/behat (or the configured cache dir). This burns people who assume behat.yml is re-read every run.
ParameterBag escaping bites % in step text. If your feature files contain literal % (percent-off pricing, format strings), Symfony's ParameterBag resolver will try to interpret it and either throw or mangle it. Escape as %% or check whether the extension calls resolveValue at all — some ParameterBag wrappers only resolve on explicit get(), some eagerly resolve on set(). Read setParameter/resolveValue in the vendor code.
resolveString vs get semantics. get() returns the raw value (which may itself be a placeholder), resolveString()/resolveValue() resolves the chain. If a parameter points to another parameter (base_url: '%domain%/app'), you must use the resolve method consistently, or you'll ship %domain%/app as a literal URL into a test.
Debug the bag in a step. A tiny @debug step or a BeforeScenario hook that dumps $this->parameterBag->all() is worth more than any log line — it tells you immediately whether a value is missing, unresolved, or overridden by a higher-precedence profile.
Behat's --strict and unknown parameters. If the extension doesn't validate that every referenced %param% exists, a typo silently becomes a literal string and your test "passes" against a nonsense URL. Add your own validator in the Context constructor: iterate parameters, call has(), and fail fast.
Fork or vendor-patch before extending. With no dependents, there's no community to triage issues. If you need a feature (e.g. env var resolution, JSON loader), fork the repo, tag it, and point Composer at the VCS — don't wait on upstream PRs. Keep the fork's namespace intact so upgrades are a composer.json edit.
Test the resolution layer in isolation. Add a small unit test around whatever class you wrap the bag in (ParameterBagResolverTest). Since the package has no tests of its own, this is your only safety net if you later swap the extension for a hand-rolled version — which, given the score, is a realistic migration path.
How can I help you explore Laravel packages today?