From 5e3583d63836f2a3e0ef58604b8905e4c714ff33 Mon Sep 17 00:00:00 2001 From: Simon Asika Date: Sun, 15 Dec 2024 18:07:54 +0800 Subject: [PATCH] If load a DB item with value which not exists in Enum, throw a readable error message https://github.com/windwalker-io/core/issues/1115 --- src/Cast/CastManager.php | 4 ++-- src/Hydrator/EntityHydrator.php | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Cast/CastManager.php b/src/Cast/CastManager.php index d54ef6a..044a862 100644 --- a/src/Cast/CastManager.php +++ b/src/Cast/CastManager.php @@ -170,7 +170,7 @@ public function castToCallback(mixed $cast, int $options, string $direction = 'h if (class_exists($cast)) { // Cast interface if (is_subclass_of($cast, CastInterface::class)) { - return static function (mixed $value, ORM $orm) use ($options, $direction, $cast) { + return static function (mixed $value, ORM $orm) use ($cast, $options, $direction) { return $orm->getAttributesResolver() ->createObject($cast) ->$direction($value); @@ -178,7 +178,7 @@ public function castToCallback(mixed $cast, int $options, string $direction = 'h } // Pure class - return static function (mixed $value, ORM $orm) use ($options, $cast) { + return static function (mixed $value, ORM $orm) use ($cast, $options) { if (is_subclass_of($cast, \BackedEnum::class)) { return $cast::wrap($value); } diff --git a/src/Hydrator/EntityHydrator.php b/src/Hydrator/EntityHydrator.php index 2610dee..342d409 100644 --- a/src/Hydrator/EntityHydrator.php +++ b/src/Hydrator/EntityHydrator.php @@ -219,6 +219,10 @@ public static function castFieldForHydrate( try { $value = $hydrator($value, $metadata->getORM(), $entity); } catch (Throwable $e) { + if ($hydrator instanceof \Closure) { + $hydrator = static::extractCastNameFromClosure($hydrator); + } + $castName = is_object($hydrator) ? $hydrator::class : json_encode($hydrator); throw new CastingException( @@ -260,4 +264,26 @@ public static function castArray(EntityMetadata $metadata, array $data, ?object return $data; } + + /** + * @param \Closure $hydrator + * + * @return mixed + * + * @throws \ReflectionException + */ + protected static function extractCastNameFromClosure(\Closure $hydrator): mixed + { + $ref = new \ReflectionFunction($hydrator); + + if ($caster = $ref->getClosureUsedVariables()['caster'] ?? null) { + $ref = new \ReflectionFunction($caster); + + if ($cast = $ref->getClosureUsedVariables()['cast'] ?? null) { + $hydrator = $cast; + } + } + + return $hydrator; + } }