Skip to content

Add deepclone_hydrate() function#6

Merged
nicolas-grekas merged 1 commit intomainfrom
hydrate
Apr 12, 2026
Merged

Add deepclone_hydrate() function#6
nicolas-grekas merged 1 commit intomainfrom
hydrate

Conversation

@nicolas-grekas
Copy link
Copy Markdown
Member

@nicolas-grekas nicolas-grekas commented Apr 11, 2026

New function: deepclone_hydrate(object|string $object_or_class, array $scoped_vars = [], array $mangled_vars = []): object

  • Instantiates a class without calling its constructor (or hydrates an existing object) and sets properties including private, protected, and readonly ones
  • $scoped_vars (keyed by declaring class) is the fastest path — direct property slot writes with no key parsing
  • $mangled_vars accepts mangled key format ("\0Class\0prop", "\0*\0prop") for convenience with (array) casts
  • Special "\0" key for SPL classes: ArrayObject/ArrayIterator constructor args, SplObjectStorage attach pairs
  • Preserves PHP & references with correct ZEND_REF_ADD/DEL_TYPE_SOURCE for typed properties
  • Instantiability validation matching deepclone_from_array rules (Reflector, Closure, NOT_SERIALIZABLE, internal create_object), cached per class
  • ValueError on integer keys in $mangled_vars or non-array values in $scoped_vars
  • Scoped hydrate: 0.6 µs/iter — 2x faster than Reflection, 2.8x faster than Closure::bind
  • All parameters renamed to snake_case ($allowed_classes, $object_or_class, etc.)
  • Version bumped to 0.2.0

@nicolas-grekas nicolas-grekas force-pushed the hydrate branch 2 times, most recently from 21d7c58 to fd64e95 Compare April 11, 2026 20:43
nicolas-grekas added a commit to symfony/polyfill that referenced this pull request Apr 11, 2026
Add pure-PHP implementation of deepclone_hydrate(object|string, array $properties, array $scopedProperties): object

Matches the C extension (symfony/php-ext-deepclone#6):
- Flat $properties with mangled key format ("\0Class\0prop", "\0*\0prop")
- Pre-scoped $scopedProperties keyed by declaring class
- SPL special "\0" key for ArrayObject, ArrayIterator, SplObjectStorage
- PHP & reference preservation
- Instantiability validation via getClassReflector()
- ValueError on integer keys or non-array scoped values
- Enum rejection in getClassReflector()
nicolas-grekas added a commit to symfony/polyfill that referenced this pull request Apr 11, 2026
Add pure-PHP implementation of deepclone_hydrate(object|string, array $properties, array $scopedProperties): object

Matches the C extension (symfony/php-ext-deepclone#6):
- Flat $properties with mangled key format ("\0Class\0prop", "\0*\0prop")
- Pre-scoped $scopedProperties keyed by declaring class
- SPL special "\0" key for ArrayObject, ArrayIterator, SplObjectStorage
- PHP & reference preservation
- Instantiability validation via getClassReflector()
- ValueError on integer keys or non-array scoped values
- Enum rejection in getClassReflector()
nicolas-grekas added a commit to symfony/polyfill that referenced this pull request Apr 11, 2026
Add pure-PHP implementation of deepclone_hydrate(object|string, array $properties, array $scopedProperties): object

Matches the C extension (symfony/php-ext-deepclone#6):
- Flat $properties with mangled key format ("\0Class\0prop", "\0*\0prop")
- Pre-scoped $scopedProperties keyed by declaring class
- SPL special "\0" key for ArrayObject, ArrayIterator, SplObjectStorage
- PHP & reference preservation
- Instantiability validation via getClassReflector()
- ValueError on integer keys or non-array scoped values
- Enum rejection in getClassReflector()
@nicolas-grekas nicolas-grekas force-pushed the hydrate branch 2 times, most recently from ad02f3f to f38694a Compare April 12, 2026 08:42
nicolas-grekas added a commit to symfony/polyfill that referenced this pull request Apr 12, 2026
…ekas)

This PR was merged into the 1.x branch.

Discussion
----------

[DeepClone] Add deepclone_hydrate() polyfill

Pure-PHP implementation of `deepclone_hydrate(object|string $object_or_class, array $scoped_vars = [], array $mangled_vars = []): object`, matching the C extension (symfony/php-ext-deepclone#6).

- `$scoped_vars` writes directly with `Closure::bind` for scope access
- `$mangled_vars` resolves mangled keys (`"\0Class\0prop"`, `"\0*\0prop"`) to the correct scope
- SPL special `"\0"` key: ArrayObject/ArrayIterator constructor, SplObjectStorage attach
- PHP `&` reference preservation via `$object->$name = $value; $object->$name = &$value;`
- Instantiability validation reuses `getClassReflector()` (same rules as `deepclone_from_array`)
- `ValueError` on integer keys in `$mangled_vars` or non-array values in `$scoped_vars`
- Fix: `getClassReflector()` now rejects enums
- All parameters renamed to snake_case (`$allowed_classes`, `$object_or_class`, etc.)

Commits
-------

626b477 [DeepClone] Add deepclone_hydrate() polyfill
@nicolas-grekas nicolas-grekas merged commit a27d7e0 into main Apr 12, 2026
20 checks passed
@nicolas-grekas nicolas-grekas deleted the hydrate branch April 12, 2026 10:09
nicolas-grekas added a commit to symfony/symfony that referenced this pull request Apr 12, 2026
…nd Instantiator (nicolas-grekas)

This PR was merged into the 8.1 branch.

Discussion
----------

[VarExporter] Leverage deepclone_hydrate() in Hydrator and Instantiator

| Q             | A
| ------------- | ---
| Branch?       | 8.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

`Hydrator::hydrate()` and `Instantiator::instantiate()` now delegate directly to `deepclone_hydrate()` from `symfony/polyfill-deepclone` (or the native `ext-deepclone`).

This removes ~350 lines of internal hydration/instantiation machinery:
- `Internal\Hydrator` class deleted — `$propertyScopes` / `getPropertyScopes()` and the two constants moved to `LazyObjectRegistry` where they belong (used by the lazy proxy infrastructure)
- `Internal\Values` class deleted (unused)
- `Hydrator::hydrate()` is now a one-liner delegate
- `Instantiator::instantiate()` is now a thin try/catch wrapper for exception mapping

The `deepclone_hydrate()` function handles:
- Scoped property writes via `EG(fake_scope)` + direct OBJ_PROP slot access (readonly, typed, references)
- Mangled property resolution from `(array)` format
- SPL special cases (ArrayObject, ArrayIterator, SplObjectStorage)
- Instantiability validation (same rules as `deepclone_from_array()`)

Depends on symfony/polyfill#568 and symfony/php-ext-deepclone#6.

Commits
-------

de52ade [VarExporter] Leverage deepclone_hydrate() in Hydrator and Instantiator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant