Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129721 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 D5FD01A00BC for ; Tue, 30 Dec 2025 07:41:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1767080523; bh=HgxgsAWsZF2U8JvwZ55R4cFKggwUEFtL0PbE4JBkkRA=; h=From:Subject:Date:References:To:In-Reply-To:From; b=n6mqBdXRYjKKHClH1E5s7uJ6WgrIqaEz6I97U0z/VG9OhLklrxvRmKT+An3VPWzkN DILQV3FJqoAopc+74wk0/wE1IJiiptm9UgyoX4zBJnK7YrxYcGhMciQpmfkpV7AkxW U+XyAWlQjc3C6wYKmHrT/RF/Fxx+erHzTqSFPEaPHq+mAnTckOJO6y6UTtc4h4pVhX sjc6hWKPY1/pCA/9ZjIpwI1m6e7wGjNZkoyc3ujuKoWvMv+ch3FsIvJ3U456yLwHHf vYwnJ3v3yrkSJR/jicLNxzYSStbmXrmKrIMliwX1Z6yRJ7NtbDQAJU2TgV0o4WESw8 S1fE0knLWxxiQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0C66A180560 for ; Tue, 30 Dec 2025 07:41:59 +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, T_SPF_TEMPERROR autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com [209.85.208.52]) (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:41:58 +0000 (UTC) Received: by mail-ed1-f52.google.com with SMTP id 4fb4d7f45d1cf-64d1ef53cf3so9350253a12.0 for ; Mon, 29 Dec 2025 23:41:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767080512; x=1767685312; 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=XIp8llkWM8Ng5P/5lhWfwII8pSLVI/aVBISI7UnkpFY=; b=cTtPg3mFT3HELcXIk9o2Z/qMtt+amxzy9ZvdH2HrSn9yIsHO7ovkYFlZLARamli5Hx KZ/IcKcXqVH0R5Ap6eHJnCkdU5t8wb3VU69sV/RdyLRAp1ZJpM27Pqbwj0ctA1vzi0x7 oXCfzHqjTqYpMMkqWLlfYu64lZr/3C/VbOBS4DeV+niRUqdAJrFZgUfvtLEnY4bbWkBd LvGKJ7xf3MxS+cpCkSaBrDeOkhBdfAUDrKmYOkp3QFqHyXVp7TFP0Lk6NsjvERPSEfhy YshraDcIDG7GGww7+s77a1DZ++4cjdm2s7zaSKLPzC+YxAUX6Tg+5/+kc8Q2eAK3saCG e1aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767080512; x=1767685312; 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=XIp8llkWM8Ng5P/5lhWfwII8pSLVI/aVBISI7UnkpFY=; b=tJsl26YFqk2JuiqOfgN4Y78iUoE2bzNiSLnTwuuu/iHFnFr8nOwq1wvaIz/xCorUmY CXl6Lm4et//afWD18XqWvZz3cMKF86Noz6a41GKyL3Jjls4GkEsD+odVYxxvI9zWLB99 Tmb+wEAR6GcTPV1/GdTz1vRemKiOhUiLDnVIrgkjjcBMTzKM8pgcnGh+Fcx6RpZlPkVQ WxNYiyMgzibLIeWtTYwUAJSdCF3GPL1U+L1Bx8R3/EaPflfedIDlnrV1sIcUGhIaS7wk 2TH7RkKGYfa/3/0VGvutu7GCBBywvoA/ZHwdLcp9ixkcU2gUttdvWSa+3E9nnskGckeS h4ow== X-Gm-Message-State: AOJu0YyvkEa3GCYssI9P8CIQsB5vfC8L7wqr/jKljiTI07lhJt4VMk8Q zSNH+GA5QNcsPKTX+M+7H1Lv68ca3xKfiJ4yqbg018g+gAx6l2LQO1P8SVeLnw== X-Gm-Gg: AY/fxX5riSLn2EZH7Te6pFy+GmtdPi7EzlIGg4cEnzWrKRmJcHN2PtawfROrmFYzjsp k/+IjMJED5CLm+9Z5n3zd4PpZjPJ+8QKCfkoHO3BNL9UnhzhCNLrf0eY67CQOIuBvsDGMdsmWdA eEj1xQjC2XDXPdAyBe7lMOApwGbg10s5NID1xjD8685f8EatHNXQdosJ/eKVIvKULurah9U+Goy jQaxfTfFUezKQlZL5NWD2MQY5n+VNxaXFJQPTG1gUFBhdFwMDeBo3jkfQ97A++1fw4hEKjKwcsM eH9myQSRwB1fSeY39oqzUpj8AcKYo4VJ0xUmvxqJ7GTaXAw6V1Lm7WEfxPoZDwyjIxV8AhMRpxy 8hTL8Y4RZnHx9JxcVdr8F3t7ugZnUPAxzKI9Ia4MYSgmfo1NilGVwyZTIi7XO6YT/UdHQMQemgt 0R0ksbTnpdO3vxYK0UyMBc202he3mblWUvZw== X-Google-Smtp-Source: AGHT+IGBfEM0fPVZqcHcs5Dw7yRmBdWYQ8gVZw39NxsR4oFZQNTrTge8RJBAUaGpstTUdjjwSsufag== X-Received: by 2002:a05:6402:535b:20b0:64c:62f7:1ac4 with SMTP id 4fb4d7f45d1cf-64c62f71cb9mr23049246a12.32.1767080512131; Mon, 29 Dec 2025 23:41:52 -0800 (PST) Received: from smtpclient.apple ([2a02:2f0c:c107:3700:7cf6:6834:a468:abc4]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-64b916b82e7sm36480604a12.35.2025.12.29.23.41.51 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Dec 2025 23:41:51 -0800 (PST) Content-Type: multipart/alternative; boundary="Apple-Mail=_6CD55905-F097-4C88-80C7-3B621A6E0569" 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:41:40 +0200 References: <998d891b-d4f9-4fc1-9c71-d7607052506a@app.fastmail.com> To: PHP Development In-Reply-To: Message-ID: X-Mailer: Apple Mail (2.3826.700.81) From: azolee@gmail.com (=?utf-8?B?QU5EUsOBUyBab2x0w6FuIEd5w6FyZsOhcw==?=) --Apple-Mail=_6CD55905-F097-4C88-80C7-3B621A6E0569 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi Larry, hi Ben, Thank you - these questions are fair, and I agree they go to the core of = what needs to be justified. Clarifying the goal The intent is not to provide an alternative to existing DI containers. = If framed that way, I agree there is no strong case. What I am exploring = is whether there is room for a small, low-level mechanism that = containers (and projects that do lightweight wiring without a full = container) could optionally build on. These are two different goals, and the first one is explicitly not what = I am aiming for. Where a potential =E2=80=9Cwin=E2=80=9D could exist At this stage, this is a hypothesis, not a conclusion. The possible = benefits I am investigating are: Standardizing a common runtime mechanism Many projects independently implement very similar runtime autowiring = loops: constructor inspection, type handling, cycle detection, and error = reporting. While all of this can be done in userland, it is repeatedly = reimplemented with small differences and edge cases. Engine-level access to metadata with request-scope caching Userland implementations rely heavily on Reflection objects and repeated = allocations. In principle, an engine-level primitive could work directly = with internal structures and cache a simple constructor plan for the = duration of a request. Whether this results in a meaningful performance = improvement needs to be measured. More consistent diagnostics for failure cases When runtime autowiring fails today, error messages and behavior vary = widely between implementations. A shared primitive could provide = deterministic and actionable diagnostics for common failure modes such = as missing scalars, non-instantiable dependencies, or circular graphs. Larry=E2=80=99s lazy-proxy example is a good reference for what =E2=80=9Cw= orth it=E2=80=9D looks like: removing a large amount of complex or ugly = code by using engine-only capabilities. I am not claiming the same level = of benefit here. The question is whether the points above add up to a = smaller but still meaningful win. Why this cannot just be asserted I agree that =E2=80=9Cthis can be done in userland=E2=80=9D is the = default position, and that any move toward core needs evidence. At this = point, I do not think the case can be made without concrete data. Next step Based on your feedback (and Marco=E2=80=99s), my plan is to: implement a reference userland version with the proposed semantics, benchmark it against typical reflection-based autowiring approaches, and, if useful, compare it to a small proof-of-concept extension = implementing the same algorithm in C. This should allow us to answer concretely: whether there is a meaningful performance or complexity win, and whether the primitive would be broadly useful enough across = runtime-autowiring use cases to justify standardization. If you have guidance on what you would consider a representative = benchmark scenario or a meaningful threshold for =E2=80=9Cthis belongs = in core=E2=80=9D, I would appreciate it. Thanks again for the questions - they helped sharpen the problem = statement. Best regards, 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 20:02, Ben Ramsey wrote: >=20 > On Mon, Dec 29, 2025 at 10:24 Larry Garfield > wrote: >> On Sun, Dec 28, 2025, at 3:39 AM, ANDR=C3=81S Zolt=C3=A1n Gy=C3=A1rf=C3= =A1s 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=20 >> > developer, primarily working on large PHP codebases where=20 >> > constructor-based dependency injection is used extensively. >> > >> > Before preparing a formal RFC, I would like to clarify the scope = and=20 >> > intent of a small, opt-in idea and gather early feedback from the = list. >> > >> > The idea is to introduce a *minimal reflection-based constructor=20 >> > autowiring primitive* into the core, exposed explicitly via the=20 >> > Reflection API, for example: >> > >> > `ReflectionClass::newInstanceAutowire(array $overrides =3D [], = ?callable=20 >> > $resolver =3D null): object >> > ` >> > This proposal is intentionally narrow. To avoid misunderstandings, = I=20 >> > would like to clearly explain what the idea *does* and *does not*=20= >> > 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=20 >> > new Reflection API. >> > The semantics of the `new` operator remain unchanged. Existing code=20= >> > paths are not affected, and there is no implicit dependency = resolution=20 >> > anywhere in the language. >> > >> > *2. No global container or service registry* >> > The proposal does not introduce a global container, service = locator, or=20 >> > registry of any kind. >> > Each autowiring operation is local to the call site and bound to = the=20 >> > 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=20 >> > does not attempt to guess or discover a concrete implementation. >> > Such mappings are inherently policy decisions and vary widely = between=20 >> > frameworks. Instead, an explicit resolver callback is required if=20= >> > non-instantiable types are involved. >> > >> > *4. Scalar parameters require overrides or defaults* >> > Scalar and builtin parameters are treated as configuration values. = The=20 >> > core does not read environment variables, configuration files, or=20= >> > globals. >> > As a result, scalar parameters must either have default values or = be=20 >> > 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=20 >> > to the provided resolver callback or fails with a clear exception. = This=20 >> > keeps architectural decisions firmly in userland. >> > >> > *6. Deterministic circular dependency detection* >> > Autowiring necessarily builds an object graph. The proposal = includes=20 >> > mandatory detection of circular dependencies within that graph. >> > When a cycle is detected, a deterministic and descriptive exception = is=20 >> > 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,=20 >> > defaults) may be cached for the duration of the request. >> > No object instances are cached, no lifetimes are managed, and no=20 >> > persistent or global caches are introduced. >> > >> > At this stage, I am primarily interested in feedback on whether = this=20 >> > level of restraint is sufficient to keep the feature aligned with = PHP=E2=80=99s=20 >> > =E2=80=9Cmechanism, not policy=E2=80=9D philosophy, and whether = there are any immediate=20 >> > concerns regarding reflection, error handling, or performance. >> > >> > If the direction seems reasonable, I plan to follow up with a draft = RFC=20 >> > on wiki.php.net that incorporates the = feedback from this discussion. >> > >> > Thank you for your time and insights. >> > >> > Best regards, >> > >> > Zoli >>=20 >> 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. >>=20 >> 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. >>=20 >> --Larry Garfield >=20 >=20 > I meant to send this question yesterday=E2=80=94it pretty much sums up = Larry=E2=80=99s question, though: >=20 > What problem(s) does this solve that can=E2=80=99t or isn=E2=80=99t = already solved by a userland implementation? >=20 > I see a lot of detail on the technical aspects of what you=E2=80=99re = proposing, but I don=E2=80=99t see anything about why you=E2=80=99re = proposing it. >=20 > Cheers, > Ben >=20 --Apple-Mail=_6CD55905-F097-4C88-80C7-3B621A6E0569 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

Hi Larry, = hi Ben,

Thank you - these questions are fair, and I agree they go = to the core of what needs to be justified.

Clarifying the goal

The intent is not to provide an = alternative to existing DI containers. If framed that way, I agree there = is no strong case. What I am exploring is whether there is room for a = small, low-level mechanism that containers (and projects that do = lightweight wiring without a full container) could optionally build = on.

These are two different goals, and the first one is explicitly = not what I am aiming for.

Where a = potential =E2=80=9Cwin=E2=80=9D could exist

At this stage, = this is a hypothesis, not a conclusion. The possible benefits I am = investigating are:

  • Standardizing a common runtime = mechanism
    Many projects independently implement very similar = runtime autowiring loops: constructor inspection, type handling, cycle = detection, and error reporting. While all of this can be done in = userland, it is repeatedly reimplemented with small differences and edge = cases.

  • Engine-level access to metadata with = request-scope caching
    Userland implementations rely heavily on = Reflection objects and repeated allocations. In principle, an = engine-level primitive could work directly with internal structures and = cache a simple constructor plan for the duration of a request. Whether = this results in a meaningful performance improvement needs to be = measured.

  • More consistent diagnostics for failure = cases
    When runtime autowiring fails today, error messages and = behavior vary widely between implementations. A shared primitive could = provide deterministic and actionable diagnostics for common failure = modes such as missing scalars, non-instantiable dependencies, or = circular graphs.

Larry=E2=80=99s lazy-proxy example is a = good reference for what =E2=80=9Cworth it=E2=80=9D looks like: removing = a large amount of complex or ugly code by using engine-only = capabilities. I am not claiming the same level of benefit here. The = question is whether the points above add up to a smaller but still = meaningful win.

Why this cannot = just be asserted

I agree that =E2=80=9Cthis can be done in = userland=E2=80=9D is the default position, and that any move toward core = needs evidence. At this point, I do not think the case can be made = without concrete data.

Next = step
Based on your feedback (and Marco=E2=80=99s), my plan is = to:

  • implement a reference userland = version with the proposed semantics,
  • benchmark it against = typical reflection-based autowiring approaches,
  • and, if useful, = compare it to a small proof-of-concept extension implementing the same = algorithm in C.

This should allow us to answer = concretely:

  • whether there is a = meaningful performance or complexity win,
  • and whether the = primitive would be broadly useful enough across runtime-autowiring use = cases to justify standardization.

If you have guidance = on what you would consider a representative benchmark scenario or a = meaningful threshold for =E2=80=9Cthis belongs in core=E2=80=9D, I would = appreciate it.

Thanks again for the questions - they helped = sharpen the problem statement.

Best = regards,

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 20:02, Ben = Ramsey <ben@benramsey.com> wrote:

On Mon, Dec = 29, 2025 at 10:24 Larry Garfield <larry@garfieldtech.com> = wrote:
On Sun, Dec 28, 2025, at = 3:39 AM, ANDR=C3=81S Zolt=C3=A1n Gy=C3=A1rf=C3=A1s 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 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=E2=80=94it pretty much sums up Larry=E2=80=99s question, = though:

What = problem(s) does this solve that can=E2=80=99t or isn=E2=80=99t already = solved by a userland implementation?

I see a lot of detail on the technical aspects of what = you=E2=80=99re proposing, but I don=E2=80=99t see anything about why = you=E2=80=99re proposing it.

Cheers,
Ben


= --Apple-Mail=_6CD55905-F097-4C88-80C7-3B621A6E0569--