symfony/polyfill-deepclone
Pure-PHP implementation of the deepclone extension's functions for converting value graphs to arrays and back, preserving object identity, references, cycles, and private state—faster and more memory-efficient than serialize/unserialize.
DEEPCLONE_HYDRATE_PRESERVE_REFS flag addresses Laravel's need for shared state preservation in reactive components (e.g., Livewire) or caching layers.IS_LONG metadata (1M limit) and SPL \0 key fixes mitigate memory spikes in batch processing (e.g., Laravel queues) or graph-based data (e.g., nested Eloquent relations). v1.43.2 adds a deepclone_from_array() fast path, which is the exact code path exercised when hydrating arrays of scalars/nested arrays (model toArray() snapshots, config bags, cache payloads) — a broad but low-magnitude win.VarExporter), this polyfill ensures consistent behavior across the stack, reducing fragmentation in cloning logic. v1.43.1 tightened parity with native deepclone by separating ArrayObject/ArrayIterator storage from the cloned payload; v1.43.2 extends parity to the error contract, reporting malformed payloads the way the native extension does rather than degrading silently.__clone() logic without explicit handling.replicate() or fresh() for models with custom accessors or circular relations.ArrayObject/ArrayIterator (common in config bags, paginators, and third-party packages built on SPL) no longer risk payload/iterator state bleed after cloning.clone $user->with('posts')).Request objects for middleware transformations without side effects.| Risk | Mitigation |
|---|---|
| Scoped Mode Deprecation | Audit for DeepClone::SCOPED usage; replace with DeepClone::MANGLED. |
| Memory Limits | Test with large object graphs (e.g., audit logs) to validate 1M metadata cap. |
| PHP 8.3+ Native Conflict | Use feature detection to switch between polyfill and native deepclone. |
| SPL Iterator Regressions | Pin to v1.43.1+; v1.43.0 and below carry the ArrayObject/ArrayIterator storage defect. |
| New Error Surface (v1.43.2) | Malformed-payload cases that previously passed through with a wrong result now raise. Audit broad try/catch blocks and any code that treats a clone as infallible. |
DEEPCLONE_HYDRATE_PRESERVE_REFS be enabled globally (e.g., for all DTOs) or opt-in (e.g., only for caching)?__clone() methods or hand-rolled unserialize()-based deep copy that could now hit the strict malformed-payload check?ArrayObject or ArrayIterator instances through a clone path? These are the precise beneficiaries of the v1.43.1 fix and should be explicitly covered.deepclone (PHP 8.3+) in Laravel's critical paths (e.g., model hydration), and does the v1.43.2 array fast path narrow the gap enough to revisit earlier benchmarks?\0 keys, ArrayObject/ArrayIterator payload isolation, malformed-payload error parity, and metadata limits in CI?clone helper to automatically use the polyfill when native deepclone is unavailable?serialize()/unserialize() hacks.DEEPCLONE_HYDRATE_PRESERVE_REFS to maintain shared state across component clones.ArrayObject/ArrayIterator can now be cloned without separating their iterator bookkeeping from their data.clone or replicate()).DeepClone::SCOPED or custom deep-cloning logic; log where malformed payloads could now raise.deepclone (PHP 8.3+) in Laravel's hot paths (e.g., Model::newCollection()) and re-baseline after v1.43.2's array speedup.^1.43.1 to ^1.43.2 and run the existing cloning test suite.ArrayObject/ArrayIterator subclass retains its own storage after a deep clone (payload and internal storage remain distinct).DEEPCLONE_HYDRATE_PRESERVE_REFS with circular references.\0 keys in custom collections.ArrayObject/ArrayIterator subclasses used in config/pagination paths.DEEPCLONE_HYDRATE_PRESERVE_REFS for:
App\DTO\UserWithRoles).Illuminate\Cache\Repository).clone helper to auto-detect the polyfill:
if (!function_exists('deepclone') || defined('DEEPCLONE_HYDRATE_PRESERVE_REFS')) {
require __DIR__.'/vendor/autoload.php';
$cloned = \Symfony\Polyfill\DeepClone\deepclone($obj, $flags);
}
v1.43.1...v1.43.2); no API, flag, or behavior contract changes for well-formed graphs. Expect improved results only for malformed payloads (now reported, matching the extension) and array-dominant clones (faster hydration). Note the one behavioral nuance: previously tolerated malformed input may now throw — this is intended parity, but it is observable.deepclone — and v1.43.2 makes that switch safer by aligning polyfill and extension error semantics.^1.43.2: v1.43.1 fixed the SPL iterator storage defect, v1.43.2 adds correct malformed-payload reporting. Override any transitive constraint pinning symfony/polyfill-deepclone below these.^1.43.2 as the minimum in composer.json; a one-line constraint bump with a narrow blast radius. Do not skip past 1.43.1 on the way.ArrayObject/ArrayIterator-backed services.NotInstantiableException and ClassNotFoundException may surface in legacy code with uncloneable objects. v1.43.2 additionally makes malformed-payload errors explicit, so logs will now name a defect that previously manifested as a wrong result further downstream.ArrayObject/ArrayIterator defect produced wrong data rather than exceptions, which is why the 1.43.1 floor is a correctness control, not just hygiene. v1.43.2 shrinks this class further by making payload defects loud.DEEPCLONE_HYDRATE_PRESERVE_REFS for reference-preserving clones.^1.43.2) and the reasons (SPL iterator storage separation in 1.43.1; malformed-payload parity and array hydration speedup in 1.43.2).\0 keys may behave unexpectedly (fixed in v1.37.0).ArrayObject/ArrayIterator payload mixing (fixed in v1.43.1 — verify installed version before debugging further).var_export() format reduces overhead.| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Uncloneable Objects | Crashes with NotInstantiableException |
Validate objects before cloning; use try-catch. |
| Metadata Limit Exceeded | Silent failure or high memory usage | Audit large object graphs; split into smaller chunks. |
SPL \0 Key Issues |
Corrupted data in custom collections | Test with edge-case payloads; update serialization logic if needed. |
| ArrayObject/ArrayIterator State Bleed | Cloned object carries wrong iterator storage (silent data corruption) — v1.43.0 and below | Require symfony/polyfill-deepclone ^1.43.2; add regression test. |
| Malformed Payload Now Throws | Clone that previously returned bad data now fails fast — v1.43.2 | Expected parity with the extension; verify error handling and alerting around clone paths, and fix the upstream producer of the malformed payload. |
| PHP 8.3+ Native Conflict | Unexpected behavior if flags differ | Use feature detection to switch between polyfill and native deepclone. |
DEEPCLONE_HYDRATE_PRESERVE_REFS), the deprecated scoped mode, the 1.43.1 version floor for SPL iterator correctness, and 1.43.2 for malformed-payload error parity.// Before (scoped mode - deprecated)
$cloned = deepclone($obj, DeepClone::SCOPED);
// After (mangled-only with reference preservation)
$cloned = deepclone($obj, DEEPCLONE_HYDRATE_PRESERVE_REFS);
ArrayObject/ArrayIterator storage separation, malformed-payload error parity, metadata limits).How can I help you explore Laravel packages today?