On Mon, Dec 29, 2025 at 10:24 Larry Garfield <[email protected]> wrote:
> On Sun, Dec 28, 2025, at 3:39 AM, ANDRÁS Zoltán Gyárfás 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 am unclear what advantage this offers over the status quo, or who the > intended user is. Is the intent to be "an alternative to existing DI > containers" (in which case, what does it offer that would make me use it > instead of Symfony DI, PHP-DI, rolling my own, etc.), or is it "a tool that > existing DI containers can use to be better" (in which case, how is it > better than the existing options for them)? Those are two different goals > that would have two different designs. > > For example, lazy object proxies already existed in user-space. However, > the amount of fugly code it required was high, so moving that logic into > the engine where it could take advantage of engine-only features to provide > a far cleaner API and better performance was a win, and allows the removal > of lots of fugly code from existing projects (when they upgrade). I'm not > clear where such a win can be found with this proposal. > > --Larry Garfield I meant to send this question yesterday—it pretty much sums up Larry’s question, though: What problem(s) does this solve that can’t or isn’t already solved by a userland implementation? I see a lot of detail on the technical aspects of what you’re proposing, but I don’t see anything about why you’re proposing it. Cheers, Ben
