Sometimes you need to do something before or after the extract and hydrate
process, for example migrate old data structures, compute derived state or clean up the
result. For this, the LifecycleExtension provides four method attributes:
PreHydrate, PostHydrate, PreExtract and PostExtract.
Register the LifecycleExtension on the builder:
use Patchlevel\Hydrator\CoreExtension;
use Patchlevel\Hydrator\Extension\Lifecycle\LifecycleExtension;
use Patchlevel\Hydrator\StackHydratorBuilder;
$hydrator = (new StackHydratorBuilder())
->useExtension(new CoreExtension())
->useExtension(new LifecycleExtension())
->build();The hooks are static methods on the class being hydrated. The data hooks
(PreHydrate, PostExtract) receive the data array and must return the
(modified) array; the object hooks (PostHydrate, PreExtract) receive the
object instance.
use Patchlevel\Hydrator\Extension\Lifecycle\Attribute\PostExtract;
use Patchlevel\Hydrator\Extension\Lifecycle\Attribute\PostHydrate;
use Patchlevel\Hydrator\Extension\Lifecycle\Attribute\PreExtract;
use Patchlevel\Hydrator\Extension\Lifecycle\Attribute\PreHydrate;
final class Profile
{
public function __construct(
public string $name,
) {
}
/**
* @param array<string, mixed> $data
* @param array<string, mixed> $context
*
* @return array<string, mixed>
*/
#[PreHydrate]
public static function migrateOldData(array $data, array $context): array
{
// rename a legacy field before the object is hydrated
if (isset($data['profile_name'])) {
$data['name'] = $data['profile_name'];
unset($data['profile_name']);
}
return $data;
}
/** @param array<string, mixed> $context */
#[PostHydrate]
public static function afterHydrate(object $object, array $context): void
{
// do something with the freshly hydrated object
}
/** @param array<string, mixed> $context */
#[PreExtract]
public static function beforeExtract(object $object, array $context): void
{
// do something with the object before it is extracted
}
/**
* @param array<string, mixed> $data
* @param array<string, mixed> $context
*
* @return array<string, mixed>
*/
#[PostExtract]
public static function cleanupData(array $data, array $context): array
{
// adjust the extracted array before it is returned
return $data;
}
}The hook methods must be static, otherwise a LogicException is thrown when
the metadata is created. The object hooks receive the instance as their first
parameter instead of using $this.
PreHydrate is a good place for schema migrations: old stored data can be
upgraded to the current class structure without touching the persisted payload.