foundry
foundry copied to clipboard
Split Instantiator
Closes #388.
This PR splits the Instantator into 2 separate objects:
Instantiator: now only create the object (using constructor/no constructor/callback/named constructor)Hydrator: takes the instantiated object and hydrates it with the attributes not used to instantiate
The following is now possible:
// customize the default instantiator (defined in your bundle config)
$factory->instantiateWith(Instantiator::noConstructor()); // trigger to create w/o constructor
$factory->instantiateWithoutConstructor(); // shortcut for above
$factory->instantiateWith('factoryMethod'); // creates via Entity::factoryMethod(...)
$factory->instantiateWith([SomeCustomInstantiator::class, 'method']);
$factory->instantiateWith(function(array $attributes) {
return new ...;
});
// customize the default hydrator (defined in your bundle config)
$factory->hydrateWith(Hydrator::ALLOW_EXTRA_ATTRIBUTES);
$factory->hydrateWith(Hydrator::ALLOW_EXTRA_ATTRIBUTES|Hydrator::ALWAYS_FORCE_PROPERTIES);
$factory->hydrateWith(fn(Hydrator $h) => $h->alwaysForceProperties(['foo', 'bar']));
// fully customize
$factory->hydrateWith(function(object $object, array $attributes) {
// ...
return $object;
});
Note: if using a closure or non-Instantiator callable for the instantiator, the hydrator isn't used. This is to avoid the unset issue discussed here. I think this is better for DX (not requiring you create a custom instantiator and hydrator) but might cause problems when trying to solve the cascade: persist problem in #312.
Todo:
- [ ] Deprectations layer
- [ ] Tests
- [ ] Docs
@nikophil, could you give this an early, high-level review?