Parser Reflection 4.0.0
This is a major release that brings the library to full PHP 8.4 reflection parity: property hooks, the lazy-object API, native enum reflection, global constant reflection, and dozens of smaller gaps in the reflection API are now implemented on top of the AST — without loading the reflected code into memory.
💥 Breaking changes
- PHP 8.4 or newer is now required (previously
>=8.2). The CI matrix runs PHP 8.4 and 8.5, with 8.6 as experimental. NodeExpressionResolverno longer implicitly autoloads classes while evaluating constant expressions. Reflection stays purely static; only APIs that genuinely need a live object (e.g.invoke()) trigger class loading.- Sources are now parsed with the newest PHP grammar supported by
nikic/php-parserinstead of the grammar of the host PHP version, so files using newer syntax can be reflected from an older runtime.
🚀 New reflection classes
ReflectionEnum,ReflectionEnumUnitCaseandReflectionEnumBackedCase— full static reflection for native enums, wired intoReflectionFile/ReflectionFileNamespace(newgetEnums()method) — #189, #190, #192ReflectionConstant— reflection forconst-declared global constants — #213NodeAwareInterface— every parsed reflection object now exposes its underlying AST node viagetNode()— #200
✨ PHP 8.4 API coverage
- Property hooks:
getHook(),getHooks(),hasHook(),hasHooks(),getSettableType(),isVirtual(),isDynamic(), plus correctgetModifiers()for virtual and abstract properties — #161, #170, #171, #172, #213 - Lazy objects:
newLazyGhost(),newLazyProxy(),resetAsLazyGhost(),resetAsLazyProxy(),isLazy(),isUninitializedLazyObject(),initializeLazyObject(),markLazyObjectAsInitialized(),skipLazyInitialization(),getLazyInitializer()and raw property access (getRawValue()/setRawValue()/setRawValueWithoutLazyInitialization()) — #213 - Abstract properties in interfaces and the
finalmodifier on promoted constructor properties — #173, #213
✨ Other improvements
- Filled PHP 8.1–8.4 function-like reflection gaps:
getTentativeReturnType(),hasTentativeReturnType(),isAnonymous(),getClosureUsedVariables(),getClosureCalledClass(), and#[\Deprecated]attribute support — #213 getAttributes()now supportsReflectionAttribute::IS_INSTANCEOFfiltering — #213- Complete trait support, including
insteadofandasalias adaptations — #177 - First-class callable syntax (
strlen(...)) supported in constant expressions — #193 Enum::CASE->valueexpressions supported in constant expressions (e.g. parameter defaults) — #176- Closures (
static fn() => ...) supported in constant-expression contexts — #213 - Enum case constant introspection via the class-constant API — #213
🐛 Bug fixes
- Fixed infinite recursion in
NodeExpressionResolver::resolveExprClassConstFetch()— #178 isSubclassOf()now compares fully-qualified class names via the resolved AST name — #180__toString()for inherited methods now renders theinherits OriginalClasssection like native reflection — #181- Fixed null handling in
ReflectionParameter::getDeclaringClass()context resolution — #178
🔧 Internal & CI
- Static analysis raised to PHPStan level 10 (
phpstan/phpstan ^2.0),rector/rectorbumped to^2.0— #156 - PHP 8.6 added to the CI matrix as experimental — #201
- GitHub Actions hardened with explicit workflow permissions and kept current via Dependabot — #191, #196, #197, #198, #199
Full Changelog: 3.1.0...4.0.0