PHP 8.4 Feature Support & Known Limitations

April 27, 2026 · View on GitHub

This document describes how Go! AOP Framework handles PHP 8.4 features in proxy generation and interception, and what limitations exist.

Property Hooks

PHP 8.4 introduced property hooks (get/set) that allow defining custom accessor logic directly on properties.

How the framework uses property hooks

Go! AOP uses native property hooks to intercept property access on proxy classes. When a property is targeted by an access(...) pointcut, the framework generates proxy hooks that route reads and writes through ClassFieldAccess join points.

Properties with existing hooks cannot be intercepted

Properties that already define their own get or set hooks are intentionally skipped for access(...) interception. The framework uses native hooks internally for interception — it cannot wrap or compose with hooks that the user has already defined.

If your pointcut matches a property that has hooks, the framework will throw an InvalidArgumentException at proxy generation time.

Reference: src/Proxy/Part/AbstractInterceptedPropertyGenerator.php line 33

// Properties with existing hooks are rejected
if ($this->property->isStatic() || $this->property->isReadOnly() || $this->property->hasHooks()) {
    throw new InvalidArgumentException(...);
}

Readonly Properties

readonly properties (PHP 8.1+, including those with asymmetric visibility like public private(set) readonly) cannot be intercepted via access(...) pointcuts. PHP does not allow defining hooks on readonly properties, so the framework cannot generate interception hooks for them.

Asymmetric visibility on non-readonly properties is preserved in generated proxies. For example, public protected(set) string $name will retain its visibility modifiers in the proxy class.

Lazy Objects

PHP 8.4 introduced ReflectionClass::newLazyProxy() and ReflectionClass::newLazyGhost() for lazy object initialization. While the framework's Container uses lazy objects internally, lazy object initialization itself is not interceptable by the framework. There is no join point for the moment a lazy proxy materializes its backing instance.

Summary Table

PHP 8.4 FeatureInterception SupportNotes
Property hooks on new properties✅ Generated by frameworkUsed for access(...) interception
Properties with existing hooks❌ SkippedFramework cannot compose with user-defined hooks
Readonly properties❌ SkippedHooks not allowed on readonly properties
Asymmetric visibility (non-readonly)✅ PreservedVisibility modifiers copied to proxy
#[\Deprecated] attribute✅ PropagatedCopied to proxy methods and classes
Lazy objects (newLazyProxy)❌ Not interceptableNo join point for lazy initialization