Hey Zoli,

On Sun, 28 Dec 2025 at 10:40, ANDRÁS Zoltán Gyárfás <[email protected]>
wrote:

> Hello internals,
>
> My name is Zoltán Gyárfás András (aka Zoli). I am a long-time PHP
> developer, primarily working on large PHP codebases where constructor-based
> dependency injection is used extensively.
>
> Before preparing a formal RFC, I would like to clarify the scope and
> intent of a small, opt-in idea and gather early feedback from the list.
>
> The idea is to introduce a *minimal reflection-based constructor
> autowiring primitive* into the core, exposed explicitly via the
> Reflection API, for example:
>
> ReflectionClass::newInstanceAutowire(array $overrides = [], ?callable 
> $resolver = null): object
>
> This proposal is intentionally narrow. To avoid misunderstandings, I would
> like to clearly explain what the idea *does* and *does not* include.
>
> *Key points of the idea, explained in detail:*
>
> *1. Explicit opt-in (no change to the new operator)*
> Autowiring would only happen when the developer explicitly calls the new
> Reflection API.
> The semantics of the new operator remain unchanged. Existing code paths
> are not affected, and there is no implicit dependency resolution anywhere
> in the language.
>
> *2. No global container or service registry*
> The proposal does not introduce a global container, service locator, or
> registry of any kind.
> Each autowiring operation is local to the call site and bound to the
> current call stack. No global state is created or reused across calls.
>
> *3. No implicit interface-to-implementation mapping*
> When a constructor depends on an interface or abstract class, the core
> does not attempt to guess or discover a concrete implementation.
> Such mappings are inherently policy decisions and vary widely between
> frameworks. Instead, an explicit resolver callback is required if
> non-instantiable types are involved.
>
> *4. Scalar parameters require overrides or defaults*
> Scalar and builtin parameters are treated as configuration values. The
> core does not read environment variables, configuration files, or globals.
> As a result, scalar parameters must either have default values or be
> provided explicitly via the $overrides argument.
>
> *5. Interface and abstract types require an explicit resolver callback*
> Interfaces and abstract classes are never instantiated automatically.
> If encountered during autowiring, the core either delegates resolution to
> the provided resolver callback or fails with a clear exception. This keeps
> architectural decisions firmly in userland.
>
> *6. Deterministic circular dependency detection*
> Autowiring necessarily builds an object graph. The proposal includes
> mandatory detection of circular dependencies within that graph.
> When a cycle is detected, a deterministic and descriptive exception is
> thrown, rather than allowing infinite recursion or a stack overflow.
>
> *7. Request-scope caching of constructor metadata only*
> For performance reasons, constructor metadata (parameter lists, types,
> defaults) may be cached for the duration of the request.
> No object instances are cached, no lifetimes are managed, and no
> persistent or global caches are introduced.
>
> At this stage, I am primarily interested in feedback on whether this level
> of restraint is sufficient to keep the feature aligned with PHP’s
> “mechanism, not policy” philosophy, and whether there are any immediate
> concerns regarding reflection, error handling, or performance.
>
> If the direction seems reasonable, I plan to follow up with a draft RFC on
> wiki.php.net that incorporates the feedback from this discussion.
>
> Thank you for your time and insights.
>
> Best regards,
>
> Zoli
>

I'm unconvinced about using reflection for this: reflection is thought of a
"deep trap" for inspecting and manipulating code in ways that aren't
generally possible in userland, and isn't really a factory.
Everything you described can be implemented in userland, using existing
reflection API.

While I like the signature you are going with (or at least its direction),
I believe that a userland implementation that proves to be "so popular that
everyone would use it" is needed first.

For instance, the implementation you propose already goes towards
supporting DI systems that do autowiring at runtime, excluding those that
do some AoT compilation of factories.
Also, unless provided by resolvers, all dependencies aren't cached in any
way (also something that tends to be configurable in various DI libraries).

I suggest prroviding this as a userland library or extension first,
specifically to validate whether there is a substantial performance
improvement over current solutions.

Marco Pivetta

https://mastodon.social/@ocramius

https://ocramius.github.io/

Reply via email to