Skip to content

Adopt PHP 8.4 native lazy objects (Container, CachedAspectLoader, ReflectionConstructorInvocation) #606

Description

@lisachenko

Summary

The framework requires PHP ^8.4 but never uses the native lazy-object API (ReflectionClass::newLazyProxy()/newLazyGhost()). Three call sites re-implement it by hand. From the PHP 8.5 support audit (PR #597); user-approved modernization batch.

Targets

  1. src/Core/Container.php:197-277addLazyService() stores closures in $this->factories and materializeService() swaps values between two arrays, with re-entrancy guard comments (~242-249). newLazyProxy() gives typed, instanceof-correct services with no two-array dance. (Also makes docs/php84-limitations.md:36 — which already claims the container uses lazy objects — true; see Document PHP 8.5 support status (docs/php85-limitations.md) and fix php84-limitations.md lazy-objects claim #605.)
  2. src/Core/CachedAspectLoader.php:102-111@property AspectLoader $loader + __get() materialization is the textbook ghost-object pattern; newLazyGhost() (or a property hook) removes the magic method and its RuntimeException fallthrough.
  3. src/Aop/Framework/ReflectionConstructorInvocation.php:65-77proceed() does newInstanceWithoutConstructor() + manual getConstructor()?->invoke(...), which is what the lazy-ghost initializer sequence formalizes; adopting it is also groundwork for the gap documented in docs/php84-limitations.md ("no join point for the moment a lazy proxy materializes").

Notes

  • Keep behavior identical for eager services and for has()/getServices…() introspection; PHPStan level 10 must stay clean.
  • Item 3 is the riskiest (semantics around uninitialized props); it can be split out if it doesn't hold up in tests.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions