PHP Language Feature Support

Flow generates proxy classes for classes managed by the object framework in order to provide Dependency Injection, Aspect-Oriented Programming, lifecycle handling and object serialization support (see Object Framework). A proxy class is a generated subclass which takes over the original class name, while the original code is preserved in a class with the _Original suffix. This works both for objects retrieved through the Object Manager and for prototype objects created with the new operator.

Because proxy classes reproduce constructors, method signatures, properties and attributes of the original class, every PHP language construct which can appear in a class declaration is potentially relevant to the proxy building mechanism. Most constructs are fully supported, some have known limitations, and support for the most recent PHP features may not be implemented yet.

This reference documents the support status of PHP language constructs in proxied classes. Note that classes which don’t get a proxy class (for example because they were excluded via Neos.Flow.object.excludeClassesFromConstructorAutowiring, annotated with Flow\Proxy(false), or simply don’t need any injected code) are plain PHP classes and not affected by any of the limitations documented here.

How to read this reference

The support status is given separately for the three main subsystems which rely on generated proxy code:

  • DI – Dependency Injection: constructor injection, property and setter injection, lifecycle methods

  • AOP – Aspect-Oriented Programming: advices woven into methods of the class

  • Serialization – the generated __sleep() / __wakeup() logic used for session-scoped objects and objects holding entity references

The status values are:

  • Yes – supported, covered by the framework’s test suite

  • Partial – supported with documented limitations (see notes)

  • No – not supported; using the construct in a proxied class may lead to compile errors, runtime errors or silently incorrect behavior

  • – – not applicable to this subsystem

  • Untested – expected to work, but not explicitly covered by functional tests; treat with care and please report issues

The Since column names the Flow version which introduced full (or the documented partial) support. “≤ 8.3” means the construct has been supported at least since Flow 8.3. “≤ 9.2” means the construct was verified by tests introduced with Flow 9.2 – earlier versions may work as well, but were not explicitly verified.

Long-standing language features

Construct

DI

AOP

Serialization

Since

Notes

final classes

Yes

Yes

Untested

≤ 8.3

The final modifier is removed from the renamed original class and re-added to the proxy class, so the class remains final for userland code.

final methods

Yes

Yes

–

≤ 8.3

Supported for advised methods. Since Flow 9.0 this includes all modifier combinations, such as final public static methods with Flow\CompileStatic (#3592).

abstract classes and methods

Yes

Yes

–

≤ 8.3

Proxy classes preserve the abstract modifier.

Static methods

Yes

–

–

≤ 8.3

Static methods are intentionally never advised by AOP. Flow\CompileStatic is supported.

Private constructors

Yes

Partial

–

9.0

The proxy makes the constructor technically public but enforces the original visibility at runtime. Note that instantiating singletons with new bypasses the Object Manager registry (#3078).

Parameters passed by reference (&$foo)

Yes

Yes

–

≤ 8.3

Reference semantics are preserved, including signal/slot arguments.

Return by reference (function &foo())

Yes

No

–

9.2

The generated proxy method preserves the reference when delegating to the original implementation (#3590). Advised methods returning by reference are refused with an explanatory exception while compiling, because the reference cannot be preserved through an advice chain.

Variadic parameters (...$items)

Yes

Yes

–

9.0

Supported since Flow 9.0 (#3589): the generated code unpacks variadic arguments in parent calls and when a join point invocation reaches the original method. Known remaining gap: variadic methods of session-scoped objects, when called through the lazy session object proxy.

Generators (yield, yield from)

Yes

Yes

–

≤ 9.2

Verified including before and around advices: the generator object is passed through the advice chain and remains fully functional.

Magic methods (__call, __get, __set, __invoke, …)

Untested

Partial

Untested

≤ 8.3

__invoke, __toString, __clone (including parent chains) and __construct are tested. A user-defined __call() method may intercept internal proxy initialization calls (#3502).

__sleep() / __wakeup()

Yes

Yes

Yes

≤ 8.3

A __sleep() method implemented in the original class replaces the generated one. Note that PHP 8.5 soft-deprecates these methods in favor of __serialize() / __unserialize().

__serialize() / __unserialize()

No

No

No

–

Not recognized by the proxy builder. Since PHP prefers these methods over __sleep() / __wakeup(), implementing them in a proxied class silently disables Flow’s generated serialization logic (dependency re-injection and entity reference handling, #3593).

Traits used by the original class

Yes

Yes

Yes

≤ 8.3

Trait methods can be advised like regular methods. Conflict resolution (insteadof / as) is handled by PHP in the original class.

Typed properties

Yes

Yes

Yes

≤ 8.3

Including property injection into typed properties.

Nullable types, void, scalar type declarations

Yes

Yes

–

≤ 8.3

No known limitations.

declare(strict_types=1)

Yes

Yes

Yes

≤ 8.3

The declaration is preserved; generated proxy code runs in the same file and therefore under the same strictness.

PHP 8.0

Construct

DI

AOP

Serialization

Since

Notes

Constructor property promotion

Yes

Untested

Untested

≤ 8.3

The proxy constructor reproduces the parameters without repeating the promotion and delegates to the original constructor.

Union types

Yes

Yes

–

9.0

Earlier versions supported union types in reflection but could generate invalid proxy code. Note: the order of types in a generated signature may differ from the original (semantically equivalent).

Named arguments

Yes

Untested

–

9.2

Proxy constructors preserve the original parameter list, so instantiation with named arguments works since Flow 9.2 (#3076). The fix was not backported to older branches.

Attributes on classes and methods

Partial

Partial

–

9.0

Attributes are reproduced on the proxy class and its methods. Attribute arguments are reconstructed from reflection: constant expressions are replaced by their values, and complex object arguments may not be reproduced faithfully (#3326, #3511). Nested enums and attribute objects are handled since Flow 8.4.

Attributes on parameters and properties

No

No

–

–

Attributes on method parameters (including #[\SensitiveParameter] and attributes on promoted constructor properties) and on class properties are not reproduced in the proxy class (#3594).

static return type

Yes

Untested

–

≤ 8.3

Late static binding resolves to the proxy class, which is the desired behavior.

mixed

Yes

Yes

–

9.0

No known limitations.

match, nullsafe operator, trailing commas

Yes

Yes

–

≤ 8.3

Method body syntax is preserved verbatim.

PHP 8.1

Construct

DI

AOP

Serialization

Since

Notes

Enums

–

–

–

≤ 8.3

Enums never get a proxy class (they cannot be subclassed). Dependency injection and AOP are therefore not available in enums, which is by design.

readonly properties

Partial

Untested

No

9.0

Supported when initialized via constructor arguments (promoted or regular). Property injection into readonly properties is not possible, and deserialization cannot restore injected readonly properties (#3282).

never return type

Yes

Yes

–

9.0

Supported including before, after-throwing and around advices.

Pure intersection types (A&B)

Yes

Yes

–

9.0

Verified for parameter, return and property types, including advised methods; the types remain enforced by PHP in proxied classes.

First-class callable syntax (foo(...))

Yes

Yes

–

≤ 9.2

A callable created from a proxied method binds to the proxy implementation, which is usually the desired behavior – advices are also invoked when the method is called through such a callable.

new in initializers (parameter defaults)

No

No

–

–

A parameter default like $foo = new Foo() in a proxied method currently aborts proxy compilation (#2968).

final class constants

Untested

–

–

–

Constants of the original class are inherited by the proxy; constants generated into the proxy class do not carry types, visibility or the final modifier.

self in type declarations

No

No

–

–

Flow replaces self with static in the original class to make factory methods return the proxy type. This replacement is currently also applied to type declaration positions, where it produces invalid or incompatible code (#3581). new self() and self::CONSTANT work as expected.

PHP 8.2

Construct

DI

AOP

Serialization

Since

Notes

readonly classes

Partial

No

Partial

9.0

Constructor injection works; the proxy class preserves the readonly modifier since Flow 9.2. Combining a readonly class with AOP advices is not supported, because the woven proxy code requires additional (non-readonly) properties (#3591). Since Flow 9.2 this is refused with a clear exception while compiling the proxy classes instead of producing a proxy class which crashes with a fatal error when it is loaded. Serialization of readonly classes works as long as no advice applies; since the session scope introduces the lazy loading aspect, readonly classes cannot be session-scoped – that case is refused with a dedicated message as well. See also #3282.

DNF types ((A&B)|C)

Yes

Yes

–

9.0

Reflected and rendered correctly, including parentheses and fully qualified type names; advised methods with DNF-typed parameters and return values are covered by tests.

null, false, true as standalone types

Yes

Partial

–

9.0

true and false are fully supported. A standalone null return type is currently not supported due to a limitation in the underlying code generator library.

Constants in traits

Yes

–

–

≤ 9.2

Constants declared in traits used by proxied classes work as expected.

Dynamic properties / #[AllowDynamicProperties]

Yes

Yes

Yes

≤ 8.3

All properties added by generated code are properly declared.

PHP 8.3

Construct

DI

AOP

Serialization

Since

Notes

Typed class constants

Yes

–

–

≤ 9.2

Typed constants of the original class work as expected and their types are visible through reflection on the proxied class. Constants generated into the proxy class are still rendered without their type declaration.

#[\Override]

Yes

Untested

–

≤ 9.2

Verified for methods overriding interface and abstract class methods; the attribute remains visible through reflection on the proxied class.

Dynamic class constant fetch (self::{$name})

Yes

–

–

≤ 9.2

Works in proxied classes, including the self:: and static:: variants.

Readonly property re-initialization in __clone()

Untested

Untested

–

–

No dedicated tests exist.

Explicitly nullable parameters (PHP 8.4 deprecation)

Yes

Yes

–

8.3

Implicitly nullable parameters are reflected and rendered as explicitly nullable, so proxy classes do not trigger the PHP 8.4 deprecation.

PHP 8.4

Note

Flow 9.2 requires PHP 8.4 or later. Support for the major new language features of PHP 8.4 in proxied classes is still in development — the current status is documented below. Classes which don’t need a proxy can use all of these features without restrictions.

Construct

DI

AOP

Serialization

Since

Notes

Property hooks

No

No

No

–

Property hooks are not yet considered by the proxy builder, the reflection service or the generated serialization code. Using hooks (especially virtual properties) in proxied classes can lead to runtime errors.

Asymmetric visibility (private(set), protected(set))

No

No

No

–

Generated proxy code writes to properties from a subclass scope, which is not allowed for private(set) properties. Property injection, introduced properties and deserialization are affected.

Lazy objects API

–

–

–

–

Not used by Flow yet; replacing Flow’s DependencyProxy with native lazy objects is under discussion (#3499).

new without parentheses

Yes

Yes

–

≤ 9.2

Verified including the combination new self()->someMethod(), which interacts with the self-to-static rewriting and creates a fully initialized proxy instance.

#[\Deprecated]

Untested

Untested

–

–

Reproduced like any other attribute, with the same limitations regarding attribute arguments.

PHP 8.5

Construct

DI

AOP

Serialization

Since

Notes

clone with / clone(...)

Untested

Untested

Untested

–

Expression syntax; expected to be unaffected by proxy building, but not covered by tests yet.

Pipe operator (|>)

Untested

Untested

–

–

Method body syntax; expected to be unaffected by proxy building.

Closures in constant expressions

No

No

–

–

Closures as parameter default values or attribute arguments cannot be reproduced in generated proxy code yet and abort proxy compilation.

Final property promotion

Untested

–

–

–

Expected to work, since promotion is not repeated in the proxy constructor.

Asymmetric visibility for static properties

No

No

No

–

Same limitations as asymmetric visibility on instance properties.

#[\NoDiscard], attributes on constants

Untested

Untested

–

–

Attributes on constants are not reproduced on constants generated into proxy classes.

Known limitations at a glance

The following constructs currently don’t work in proxied classes and should be avoided until the referenced issues are resolved. As a workaround, most of them can be used in classes which are excluded from proxy building (see Configuring objects).

  • self as a parameter, return or property type declaration — #3581

  • Advised methods returning by reference (refused at compile time with an explanatory exception) — #3590

  • AOP advices on readonly classes (refused at compile time with an explanatory exception) — #3591

  • new expressions as parameter default values — #2968

  • __serialize() / __unserialize() in classes relying on Flow’s generated serialization logic — #3593

  • Attributes on method parameters and class properties (not reproduced in the proxy) — #3594

  • Property hooks and asymmetric visibility (PHP 8.4)

  • Closures in constant expressions (PHP 8.5)

If you run into a limitation which is not documented here, please report it in the flow-development-collection issue tracker.