Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129720 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 9DEA11A00BC for ; Tue, 30 Dec 2025 07:16:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1767078990; bh=NCsNgELI/BBtG7uthnPnCLig/n81hSN3MzAq94y+OWI=; h=From:Subject:Date:References:To:In-Reply-To:From; b=noHmdzATDCKxfKnHp94ykXGfMzlcscikLb8JlgOZWCzbUCCPpA7M7dmsg/9FTZuMX JsM2Z5lwQKymd5I2dN+XWNDjeRCLw5W5hIb1/NtMuTwdvIE6cdNx28rz9k/JjMmqBq 3wlaEoRcw1vq90L/BDrZPK0TquHw12M69h0KoHLNzSMKpdkuWmNWtRlQyIZyEHRJqL DVtQzhqLsSQZ+Sb3E/i0rBEUJYrfCg13zxwnt25uCsisTF+eTb9B76TPcDJKYZCr66 SYfRh+XCvXErRQepjMw/+tV1Gpyw7LIOri7inxlPcV2CB3RLMwnq2P/TQqbHAGev3I C0CpWof9atNlg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 90556180041 for ; Tue, 30 Dec 2025 07:16:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-ej1-f43.google.com (mail-ej1-f43.google.com [209.85.218.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 30 Dec 2025 07:16:28 +0000 (UTC) Received: by mail-ej1-f43.google.com with SMTP id a640c23a62f3a-b7ffbf4284dso1288779366b.3 for ; Mon, 29 Dec 2025 23:16:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767078982; x=1767683782; darn=lists.php.net; h=message-id:in-reply-to:to:references:date:subject:mime-version:from :from:to:cc:subject:date:message-id:reply-to; bh=mGFGhc9YVDX9K0a7SsylcsXzJc7zjAc+HRsLr3R30SE=; b=PHYTZtNeFTc4ekrg6gpPnSVclyGe/2gnF/3dd+/+eqvkQOdXAL/NX6q4El567GeK14 jgUvLw0x/1oDp/CuRkgntfGZtYRJeDHc62ORWyLbc6sF2RtUio0vHwful7NRsSjkIMwX tANmO86FH7pEUbu4zplQwbBJspPVSqX5rifkKmHIeimdgl8Vv7jaKkMaVX2BSaI1TrTP /dvJYjoboq+ojsNyI9myKuA2gDQUt3gZ5cLWWSLbJ266/jZ6jVV95zG3ghfEh/0ixA3Z DyCAlPwMU0nxonQyxpA9jsBRUUTQ5mi0HzWiVFBU6ORh7SBY2x5sg2tUXcxcrbXfb1P3 0t4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767078982; x=1767683782; h=message-id:in-reply-to:to:references:date:subject:mime-version:from :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=mGFGhc9YVDX9K0a7SsylcsXzJc7zjAc+HRsLr3R30SE=; b=oMbYlRqLakxho3OzUaHAT5nhg5AJrHX86/O+gLS4YimikfDXgRSTfXpf9i7K6DlBsn RfpbQe/sN22urAqvO4a6cYcXByXXprvfd4L0vn243K5W1cpcy5eftgG2m2KgYnu5hMyI mPAmr22RXvEFpn60IWVxn1NdYTqIdJUoHaMtOdhn5IOn5HopW7ge4BGFAzCT/o8YxEhD 6HvBvDnJoTHuU71z0X8xaEkBN0Tqbdv3lap6R9KQId45MIc+3ACKI+YC/jkyHDilBs6X 5lVV11833Htgp2gfOkWUJZ1TU4ayFljv1u6BmjQdih4ff/fNltJgZB/DkGR7IM3dDFbM CAJg== X-Gm-Message-State: AOJu0YwXYv6Cpf2Fd7HkikNJoftS7F25W27TJNCzw0YS8BOcihGTMerr W0XQ83khdBWyOeZGqlhyclv6aq0Wu2gEbzaIVJ2+685l6y5w37BtnSlNKm/ykA== X-Gm-Gg: AY/fxX7Nhn6l+9zy3HxVS0FyGK+/PbdEDAB7A+FTPbhqhwnfWGBzxA0Y4WC2gtc5E3R 4QHwv26LTUrup7kn1esOjj/OjkTteHHgHmuhDESiEi8kTIJWyOpr/hkBpUYfXWRt22f6KjY0JAD EMToMkczYU9SygldH+abAaGbq+eSIZIhA6OWg0vaYSFVf47F4CGk6SfarrV7AAcmWx/q9WVKjO8 dEWD29cOr1Xaz4wRTAiAXafUD03prfeTB0whi+64jQBlZY1fGFgX/dRBab0+1dIfWAmRUGDz1cK 33SbvQQdJL6O77GJpllzbmJ7V0Dkd7tcUXh1YzI4+olcakZo2Etvmq04pXGfnJyX5kVPsTlBJBo oSg2BAHDqcxaBeEuea9PcFzcvTOUgruLDBN70S5HMaPjE+fl0PYtVGIJifBhlo24Oa4evivkhZZ bAkNBO6rDFEzvVGuNFtkG0pvSpNYilM/zAXA== X-Google-Smtp-Source: AGHT+IEAheVV6S8mKFHWWOoKpjMcf4KMlfKuz9KKN3IxrK8duUV4hPJ5rjEsPT2Sz6q53uNJQGP3TA== X-Received: by 2002:a17:907:1c9c:b0:b83:37eb:34f8 with SMTP id a640c23a62f3a-b8337eb3cf0mr1409339966b.35.1767078981535; Mon, 29 Dec 2025 23:16:21 -0800 (PST) Received: from smtpclient.apple ([2a02:2f0c:c107:3700:7cf6:6834:a468:abc4]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b8037de074dsm3643629066b.44.2025.12.29.23.16.20 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Dec 2025 23:16:21 -0800 (PST) Content-Type: multipart/alternative; boundary="Apple-Mail=_621BA300-23F1-4D0A-8DA5-535B9DF83A24" Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.700.81\)) Subject: Re: [PHP-DEV] [Discussion] Reflection-based constructor autowiring (scope clarification) Date: Tue, 30 Dec 2025 09:16:09 +0200 References: To: "internals@lists.php.net" In-Reply-To: Message-ID: <6C2A8D96-BB4C-4091-85D8-21654C242364@gmail.com> X-Mailer: Apple Mail (2.3826.700.81) From: azolee@gmail.com (=?utf-8?B?QU5EUsOBUyBab2x0w6FuIEd5w6FyZsOhcw==?=) --Apple-Mail=_621BA300-23F1-4D0A-8DA5-535B9DF83A24 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi Marco, thank you for the thoughtful feedback - I agree with the concerns you = raised, as they help clarify the right next step. On Reflection: my initial motivation for using ReflectionClass was that = it already owns the =E2=80=9Cdynamic instantiation=E2=80=9D surface = (newInstance, newInstanceArgs) and provides an explicit opt-in entry = point without introducing new global concepts. That said, I fully take = your point that Reflection is primarily an inspection API and can be = seen as a =E2=80=9Cdeep trap=E2=80=9D when it starts to look like a = general-purpose factory. I don=E2=80=99t want to force that framing if = it turns out to be the wrong abstraction. On =E2=80=9Cthis can be done in userland=E2=80=9D: I agree. The proposal = is not about enabling something fundamentally impossible today, but = about whether moving a very common runtime autowiring loop (constructor = parameter analysis, type handling, cycle detection, diagnostics) closer = to the engine could provide enough benefit to justify standardization. = As you point out, that needs to be demonstrated, not assumed. Your suggestion to validate this in userland (or as an extension) first = makes sense, and I plan to follow that path before pushing further on a = core RFC. Concretely, the next steps I=E2=80=99m considering are: A reference userland implementation that follows the same strict = semantics discussed (explicit overrides, resolver for non-instantiables, = deterministic cycle detection, request-scope metadata caching). A small benchmark suite comparing: typical userland reflection-based autowiring approaches, the reference implementation, and, if feasible, a proof-of-concept extension implementing the same = algorithm in C. Using that data to answer whether there is a meaningful performance or = complexity win that userland alone cannot reasonably achieve. Regarding AoT / compiled factories: I agree that the proposed primitive = naturally aligns better with runtime autowiring, and that many = containers deliberately avoid runtime reflection for production paths. = My intent was not to replace or constrain those approaches, but to = explore whether a low-level helper could still be useful in non-compiled = modes (development, dynamic plugins, fallback paths). Whether that use = case is broad enough is exactly what the userland validation should = clarify. If you have any guidance on what you would consider a representative = benchmark or a meaningful performance threshold for =E2=80=9Cworth = moving into core=E2=80=9D, I=E2=80=99d appreciate it. Thanks again for the feedback, Zoli eng. ANDR=C3=81S Zolt=C3=A1n-Gy=C3=A1rf=C3=A1s --------------------------------------- tel: +40 745 797 798 mail: azolee@gmail.com > On 29 Dec 2025, at 13:02, Marco Pivetta wrote: >=20 > Hey Zoli, >=20 > On Sun, 28 Dec 2025 at 10:40, ANDR=C3=81S Zolt=C3=A1n Gy=C3=A1rf=C3=A1s = > wrote: >> Hello internals, >>=20 >> My name is Zolt=C3=A1n Gy=C3=A1rf=C3=A1s Andr=C3=A1s (aka Zoli). I am = a long-time PHP developer, primarily working on large PHP codebases = where constructor-based dependency injection is used extensively. >>=20 >> 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. >>=20 >> The idea is to introduce a minimal reflection-based constructor = autowiring primitive into the core, exposed explicitly via the = Reflection API, for example: >>=20 >> ReflectionClass::newInstanceAutowire(array $overrides =3D [], = ?callable $resolver =3D null): object >> This proposal is intentionally narrow. To avoid misunderstandings, I = would like to clearly explain what the idea does and does not include. >>=20 >> Key points of the idea, explained in detail: >>=20 >> 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. >>=20 >> 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. >>=20 >> 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. >>=20 >> 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. >>=20 >> 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. >>=20 >> 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. >>=20 >> 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. >>=20 >> At this stage, I am primarily interested in feedback on whether this = level of restraint is sufficient to keep the feature aligned with = PHP=E2=80=99s =E2=80=9Cmechanism, not policy=E2=80=9D philosophy, and = whether there are any immediate concerns regarding reflection, error = handling, or performance. >>=20 >> 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. >>=20 >> Thank you for your time and insights. >>=20 >> Best regards, >>=20 >> Zoli >>=20 >=20 > 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. >=20 > 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. >=20 > 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). >=20 > I suggest prroviding this as a userland library or extension first, = specifically to validate whether there is a substantial performance = improvement over current solutions. > =20 > Marco Pivetta=20 >=20 > https://mastodon.social/@ocramius >=20 > https://ocramius.github.io/ > =20 --Apple-Mail=_621BA300-23F1-4D0A-8DA5-535B9DF83A24 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

Hi Marco,

thank = you for the thoughtful feedback - I agree with the concerns you raised, = as they help clarify the right next step.

On= Reflection: my initial motivation for = using ReflectionClass was that it already owns = the =E2=80=9Cdynamic instantiation=E2=80=9D surface = (newInstancenewInstanceArgs) and = provides an explicit opt-in entry point without introducing new global = concepts. That said, I fully take your point that Reflection is = primarily an inspection API and can be seen as a =E2=80=9Cdeep trap=E2=80=9D= when it starts to look like a general-purpose factory. I don=E2=80=99t = want to force that framing if it turns out to be the wrong = abstraction.

On =E2=80=9Cthis can be done = in userland=E2=80=9D: I agree. The proposal is not about enabling = something fundamentally impossible today, but about whether moving a = very common runtime autowiring loop (constructor parameter analysis, = type handling, cycle detection, diagnostics) closer to the engine could = provide enough benefit to justify standardization. As you point out, = that needs to be demonstrated, not assumed.

Your suggestion to validate this in userland (or = as an extension) first makes sense, and I plan to follow that path = before pushing further on a core RFC. Concretely, the next steps I=E2=80=99= m considering are:

  1. A reference userland implementation that follows = the same strict semantics discussed (explicit overrides, resolver for = non-instantiables, deterministic cycle detection, request-scope metadata = caching).

  2. A small benchmark suite = comparing:

    • typical userland reflection-based autowiring = approaches,

    • the reference = implementation,

    • and, if feasible, = a proof-of-concept extension implementing the same algorithm in = C.

  3. Using that data to = answer whether there is a meaningful performance or complexity win that = userland alone cannot reasonably achieve.

Regarding AoT / compiled factories: I agree that = the proposed primitive naturally aligns better with runtime autowiring, = and that many containers deliberately avoid runtime reflection for = production paths. My intent was not to replace or constrain those = approaches, but to explore whether a low-level helper could still be = useful in non-compiled modes (development, dynamic plugins, fallback = paths). Whether that use case is broad enough is exactly what the = userland validation should clarify.

If you = have any guidance on what you would consider a representative benchmark = or a meaningful performance threshold for =E2=80=9Cworth moving into = core=E2=80=9D, I=E2=80=99d appreciate it.

Thanks again for the = feedback,

Zoli


eng. ANDR=C3=81S = Zolt=C3=A1n-Gy=C3=A1rf=C3=A1s
---------------------------------------tel: +40 745 797 798
mail: azolee@gmail.com

On 29 Dec 2025, at 13:02, Marco = Pivetta <ocramius@gmail.com> wrote:

Hey Zoli,

On Sun, 28 = Dec 2025 at 10:40, ANDR=C3=81S Zolt=C3=A1n Gy=C3=A1rf=C3=A1s <azolee@gmail.com> = wrote:

Hello internals,

My = name is Zolt=C3=A1n Gy=C3=A1rf=C3=A1s Andr=C3=A1s (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 =3D [], ?callable $resolver =3D 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=E2=80=99s = =E2=80=9Cmechanism, not policy=E2=80=9D 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.
 

= --Apple-Mail=_621BA300-23F1-4D0A-8DA5-535B9DF83A24--