foundry icon indicating copy to clipboard operation
foundry copied to clipboard

Split Instantiator

Open kbond opened this issue 2 years ago • 1 comments

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

kbond avatar Jan 10 '23 22:01 kbond

@nikophil, could you give this an early, high-level review?

kbond avatar Jan 10 '23 22:01 kbond