-
Notifications
You must be signed in to change notification settings - Fork 0
Migration Guide
v2 is a major release. It fixes bugs that changed observable behaviour, removes a problematic feature (the internal cache), and modernises the API surface. Most users only need to add one option to keep their old behaviour; some need to update assumptions about keys, merge semantics, and option validation.
If you upgraded from v1 and want the closest possible drop-in
behaviour, add caseInsensitive => true to your constructor call:
new ParameterBag($data, ['caseInsensitive' => true]);The rest of v2's changes are bug fixes — they make the bag behave the way the v1 documentation already claimed it did. Read on for the specifics so you can audit your call sites.
v1 silently lowercased every key. v2 preserves case unless you opt in.
// v1 behaviour
$bag = new ParameterBag(['User' => 'alice']);
$bag->get('user'); // 'alice'
// v2 default
$bag = new ParameterBag(['User' => 'alice']);
$bag->get('user'); // null — case-sensitive
$bag->get('User'); // 'alice'
// v2 legacy mode
$bag = new ParameterBag(['User' => 'alice'], ['caseInsensitive' => true]);
$bag->get('user'); // 'alice'See Case Sensitivity for the full mode.
v1 inverted the comparison and set isMulti = true for flat
arrays. The bug was masked whenever callers supplied the option
explicitly. v2 auto-detects correctly: nested → multi, flat → flat.
If you wrote new ParameterBag(['user' => 'a']) and relied on the
broken auto-detection to give you multi-mode dotted writes,
supply ['isMulti' => true] explicitly.
v1's merge() always used array_merge, which is shallow. v2
dispatches to array_replace_recursive when isMulti is on, so
sibling keys at every depth are preserved.
$bag = new ParameterBag(['db' => ['user' => 'root']], ['isMulti' => true]);
$bag->merge(['db' => ['pass' => 'secret']]);
$bag->all();
// v1: ['db' => ['pass' => 'secret']] (user was wiped)
// v2: ['db' => ['user' => 'root', 'pass' => 'secret']]If you wanted the v1 shallow behaviour even with nested data, run
the bag in flat mode (['isMulti' => false]).
v1 kept an internal cache that survived clear(), so a subsequent
get() could return a value that no longer existed in the stack.
v2 removed the cache entirely; clear() and close() are
authoritative.
v1 used the same magic-string sentinel for both, so storing null
made has() return false and get() return the default. v2's
has() uses array_key_exists and get() returns the stored
value, so null is a first-class value:
$bag = new ParameterBag(['role' => null]);
// v1
$bag->has('role'); // false
$bag->get('role', 'fallback'); // 'fallback'
// v2
$bag->has('role'); // true
$bag->get('role', 'fallback'); // nullv1 used '__InitPHPP@r@m£t£rB@gN0tF0undV@lu€__' as an internal
"not found" sentinel. Storing that exact string as data broke
has() and get(). v2 uses a private object sentinel that callers
cannot construct, so any string — including the legacy one — can be
stored safely.
v1's normaliser ran trim($value, $separator) on every string
leaf in multi mode, silently corrupting data like
'.example.com.' → 'example.com'. v2 only trims keys.
v1's remove() used the first argument as the parent slot for
every iteration in the multi-mode branch, so
remove('db.pass', 'cache.ttl') either deleted the wrong slot or
created a phantom one. v2 derives the parent slot from the current
iteration.
| Method | Purpose |
|---|---|
isEmpty(): bool |
Cheap top-level emptiness check. |
keys(): array |
Top-level keys in insertion order. |
values(): array |
Top-level values in insertion order. |
replace(array $data): self |
Swap the stack, preserve options. |
\ArrayAccess, \Countable, \IteratorAggregate
|
Now implemented on the bag and declared on ParameterBagInterface. |
See Iteration & Counting and the full API Reference.
| Item | Status | Notes |
|---|---|---|
_PBStack, _PBOptions, _PBCache
|
Removed | These were private in v1 too. If you accessed them via reflection, switch to the new typed properties ($stack, $isMulti, $separator, $caseInsensitive). |
__destruct() |
Removed | PHP's GC reclaims memory automatically. If you relied on it to reset options, call close() explicitly. |
// v1 — silently ignored
new ParameterBag([], ['is_multi' => true]);
// v2 — throws
new ParameterBag([], ['is_multi' => true]);
// ParameterBagInvalidArgumentException:
// "Unknown ParameterBag option(s): is_multi.
// Known options: isMulti, separator, caseInsensitive."The exception message lists every accepted key — useful for quickly finding the right name in IDEs and logs.
| v1 | v2 | |
|---|---|---|
| Advertised minimum | PHP 7.2 | PHP 7.4 |
| Tested matrix | n/a | 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 |
PHP 7.2 has been EOL since 2019. v2's minimum (7.4) gets typed properties; signatures avoid features that landed in 8.0+ so the library still compiles on 7.4 unchanged.
If you cannot make the full migration immediately, the following factory mimics v1's defaults while still benefitting from every v2 bug fix:
use InitPHP\ParameterBag\ParameterBag;
function legacyParameterBag(array $data = [], array $options = []): ParameterBag
{
return new ParameterBag(
$data,
$options + ['caseInsensitive' => true]
);
}Only the case-sensitivity default is rolled back. The isMulti
auto-detection, recursive multi-mode merge, value-trim fix,
distinguishable null, and strict option validation are all kept.
When upgrading a non-trivial project, walk through this list:
- All
new ParameterBag(...)call sites: do any rely on the old case-insensitive default? AddcaseInsensitive => true. - Any
set('User.foo', ...)writes followed byget('user.foo')reads? Pick one case consistently or opt into case-insensitive. - Any
merge()calls with nested payloads that previously "happened to work" becauseisMultiwas wrong? Verify the bag is in the mode you expected. - Any code that relied on
has(null-value)returning false? Switch toget($key) === nullfor that specific check. - Any code that previously caught surprises from the cache? The cache is gone; the bug should be gone too. Remove the workaround.
- Any option keys spelled differently in different files? v2 will throw at construction; fix the typos before deploying.
initphp/parameterbag · MIT License · part of the InitPHP family
Source · Issues · Discussions · Packagist · Contributing · Security Policy
Getting Started
Core Usage
Reference
Practical Guides
Migration & Help