From c042795eece87b6837bcd1d4f2bc55b62ca8c69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8E=9F=E7=82=B9?= <467490186@qq.com> Date: Thu, 27 Aug 2026 16:49:40 +0800 Subject: [PATCH 1/2] fix(attribute): mark ClassConstFetch as lazy to resolve enum attribute args ClassConstFetch expressions (e.g. Status::Active) in attribute arguments were not marked as lazy values, so the PHPX bridge stored the backing string value instead of calling the factory that resolves the enum case. Add ClassConstFetch to requiresLazyValue() so the lazy marker is set and the factory function is invoked at runtime via typephp_attribute_set_lazy_value_argument(). --- src/Transform/RuntimeAttributeFactoryLowering.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Transform/RuntimeAttributeFactoryLowering.php b/src/Transform/RuntimeAttributeFactoryLowering.php index 017d25de..f6683116 100644 --- a/src/Transform/RuntimeAttributeFactoryLowering.php +++ b/src/Transform/RuntimeAttributeFactoryLowering.php @@ -131,6 +131,7 @@ private function requiresLazyValue(Expr $value): bool // though it is not represented by an Array_ AST node. || $node instanceof Expr\Cast\Array_ || $node instanceof Expr\Cast\Object_ + || $node instanceof Expr\ClassConstFetch || (($node instanceof Expr\FuncCall || $node instanceof Expr\StaticCall) && $node->isFirstClassCallable()); }) !== null; From 5a92f256d8352402d2645bc0d7d4cc5acb32a544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8E=9F=E7=82=B9?= <467490186@qq.com> Date: Thu, 27 Aug 2026 17:36:20 +0800 Subject: [PATCH 2/2] fix(attribute): mark top-level ClassConstFetch as lazy to resolve enum attribute args --- src/Transform/RuntimeAttributeFactoryLowering.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Transform/RuntimeAttributeFactoryLowering.php b/src/Transform/RuntimeAttributeFactoryLowering.php index f6683116..fa77c144 100644 --- a/src/Transform/RuntimeAttributeFactoryLowering.php +++ b/src/Transform/RuntimeAttributeFactoryLowering.php @@ -124,6 +124,10 @@ private function requiresLazyValue(Expr $value): bool return true; } + if ($value instanceof Expr\ClassConstFetch) { + return true; + } + return (new NodeFinder())->findFirst($value, static function (Node $node): bool { return $node instanceof Expr\New_ || $node instanceof Expr\Closure @@ -131,7 +135,6 @@ private function requiresLazyValue(Expr $value): bool // though it is not represented by an Array_ AST node. || $node instanceof Expr\Cast\Array_ || $node instanceof Expr\Cast\Object_ - || $node instanceof Expr\ClassConstFetch || (($node instanceof Expr\FuncCall || $node instanceof Expr\StaticCall) && $node->isFirstClassCallable()); }) !== null;