Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127893 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 9AFE91A00BC for ; Fri, 4 Jul 2025 22:55:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1751669620; bh=og8mBnIqMoyU9xJSgku76z+fbUr0OPvli7pl/fG+ITQ=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=DcBOvx0hAJ7G2WfQeeG27xf7yfWRYGIZe+bdNMm/epiquiWXQ5+5iZxmvJ744qBzl jkv2uPwNFJ8yCYDa+5G7iujfvVFqcmJ+Bt+xPSUpyo/TNrDE2Q7KmnhHYpLkTEaTpt +kPHBKTAdps6q+PhdVT2839Q4jJtGgPcPPnl4bueUgzhJTUL4/yPpYdp4/f5zO2GGp 1dhV9I1S6XtdfslHlrZH8PDY9ksjhlBrAE3O7bV3qLfowjqkEEgCi5u3k+cHOqruv6 9CypTDLBMjxX5OHOvWPmJYApCjNV1bH8/pFQZq3IKasRVvKwQOdYUGuRBHwEXJGJo8 Y0UqmRn7Ooj8w== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C8EEA180882 for ; Fri, 4 Jul 2025 22:53:36 +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=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from fhigh-b6-smtp.messagingengine.com (fhigh-b6-smtp.messagingengine.com [202.12.124.157]) (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 ; Fri, 4 Jul 2025 22:53:34 +0000 (UTC) Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfhigh.stl.internal (Postfix) with ESMTP id 2379E7A00CB; Fri, 4 Jul 2025 18:55:26 -0400 (EDT) Received: from phl-imap-06 ([10.202.2.83]) by phl-compute-05.internal (MEProxy); Fri, 04 Jul 2025 18:55:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1751669725; x= 1751756125; bh=m7toNyOhMe/8M20nZ4Eb0Pim7bihSA6txWnznauCCb0=; b=f IPS2Q3tN+hOazAUTkYFM2A4GD3a8U4lIeqnnHSp/LNGGS1tlu23Q/Bt1WR5kGwFM HjGus5bXB0j28Nc3qt4j36q9o7FElBk3gfTqvEu33YDztsyw3myFM7uDSJnAXuZ4 6eu2jH75XqqhKclyfUFUSnoMdm6ayYKVcMhAKYUebK3ap9f4lBrQpEMKm5So/21K YuvvwhhqdgBwcNzEHR63b4x/5ljy0gcHT9jdP/DEUtwRMdKHtJKzM3LQpgU+I0ZZ WPoCNxPoaWLqwdUUDWr4AjwCbfES3p50MY53aipnL1308dX3W/UjXhfs678y34wJ pOusrwBrQ58XOfsm8qLcA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t= 1751669725; x=1751756125; bh=m7toNyOhMe/8M20nZ4Eb0Pim7bihSA6txWn znauCCb0=; b=bRZPTfaLfaxPrDjDN1+0OlIwLgrmIx4XeDqwfWFfWQ2tREvIFQs g5ahPeW/Y+QrzCQr4r1vzAqbiRAJWlvu5uFvdCgo+4TXUmvj1pipa63HEgz7DJh7 Os4TaEKl5tCPljYfNFnQFrzzBAvY8lJQF3+T0WiLe6v8puo1r+Jq8aend3pfnZVP CA7Pzrju9dstmioyceGq7hwqkMzKm47VbjcncW3rYBx1adkG7f1784Tw26EkiJQQ /exbaZq9eeXhA4Jf2YonVb5IUnm3j4EuqljO7OyFfzClgo2vq1DQYY+qw66FQqvr ZPNEIzpkvsirlzVZBtPm9sRBq0aRqPb0nZg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgddvgeegudcutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenogfuuh hsphgvtghtffhomhgrihhnucdlgeelmdenucfjughrpefoggffhffvvefkjghfufgtsegr tderreertdejnecuhfhrohhmpedftfhosgcunfgrnhguvghrshdfuceorhhosgessghoth htlhgvugdrtghouggvsheqnecuggftrfgrthhtvghrnhepleevteehheelhefgveeiuddu ieduffekvdfhudevkeekgeeiveekgfelvdeigfdtnecuffhomhgrihhnpehgihhthhhusg drtghomhdpfehvgehlrdhorhhgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghm pehmrghilhhfrhhomheprhhosgessghothhtlhgvugdrtghouggvshdpnhgspghrtghpth htohepgedpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtoheprghnughrvggrshesughq gihtvggthhdrnhgvthdprhgtphhtthhopehlrghrrhihsehgrghrfhhivghlughtvggthh drtghomhdprhgtphhtthhopehphhhpqdhlihhsthhssehkohgrlhgvphhhrghnthdrtgho mhdprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 753B1240008E; Fri, 4 Jul 2025 18:55:25 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: T8ffec5e1f43e82e3 Date: Sat, 05 Jul 2025 00:55:05 +0200 To: "Andreas Hennings" Cc: "Stephen Reay" , "Larry Garfield" , "php internals" Message-ID: <731322ff-ff9f-4ab2-a4a7-7313e5f2b19c@app.fastmail.com> In-Reply-To: References: <1cfc477a-781f-40e9-9e37-dd748ef261be@app.fastmail.com> <20DACB49-3C84-4B23-98E2-35050D9EDAC9@koalephant.com> <3C4ED1AE-3E25-461D-8C3C-AF954499F905@koalephant.com> <4839a478-9b65-4ac5-8444-ca286ddc72fd@app.fastmail.com> Subject: Re: [PHP-DEV] [RFC idea] Target-aware attributes Content-Type: multipart/alternative; boundary=e6b9c2f0ecf34137ae3663b151b2718f From: rob@bottled.codes ("Rob Landers") --e6b9c2f0ecf34137ae3663b151b2718f Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sat, Jul 5, 2025, at 00:47, Andreas Hennings wrote: > On Sat, 5 Jul 2025 at 00:11, Rob Landers wrote: > > > > > > > > On Fri, Jul 4, 2025, at 17:21, Andreas Hennings wrote: > > > > On Fri, 4 Jul 2025 at 06:30, Stephen Reay = wrote: > > > > > > > > > > > > On 4 Jul 2025, at 00:54, Andreas Hennings wr= ote: > > > > > > On Thu, 3 Jul 2025 at 19:17, Stephen Reay wrote: > > > > > > > > > > > > > > > > > > Sent from my iPhone > > > > > > On 3 Jul 2025, at 23:40, Larry Garfield w= rote: > > > > > > =EF=BB=BFOn Wed, Jul 2, 2025, at 5:26 PM, Andreas Hennings wrote: > > > > > > This topic was discussed in the past as "Declaration-aware > > > attributes", and mentioned in the discussion to "Amendments to > > > Attributes". > > > I now want to propose a close-to-RFC iteration of this. > > > (I don't have RFC Karma, my wiki account is "Andreas Hennings (don= quixote)") > > > > > > ----- > > > > > > Primary proposal > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > > > > > I propose to introduce 3 new methods on ReflectionAttribute. > > > > > > static ReflectionAttribute::getCurrentTargetReflector(): ?Reflector > > > Most of the time, this will return NULL. > > > During the execution of ReflectionAttribute->newInstance(), it will > > > return the reflector of the symbol on which the attribute is found. > > > (in other words, during > > > $reflector->getAttributes()[$i]->newInstance(), it will return > > > $reflector.) > > > During the execution of > > > ReflectionAttribute::invokeWithTargetAttribute($target, $callback)= , it > > > will return $target. > > > If the call stack contains multiple calls to the above mentioned > > > methods, only the closest/deepest one counts. > > > (This means that php needs to maintain a stack of reflectors.) > > > > > > > > > *snip* > > > > > > Other alternatives > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > > > > > In older discussions, it was suggested to provide the target refle= ctor > > > as a special constructor parameter. > > > This is problematic because an attribute expression #[MyAttribute(= 'a', > > > 'b', 'c')] expects to pass values to all the parameters. > > > > > > Another idea was to provide the target reflector through a kind of > > > setter method on the attribute class. > > > This can work, but it makes attribute classes harder to write, bec= ause > > > the constructor does not have all the information. > > > It may also prevent attribute classes from being stateless (depend= ing > > > how we define stateless). > > > > > > > > > Userland implementations > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > > > > > > One userland implementation that was mentioned in this list in the > > > past is in the 'crell/attributeutils' package. > > > This one uses a kind of setter injection for the target reflector. > > > See > > > https://github.com/Crell/AttributeUtils/blob/master/src/FromReflec= tionClass.php > > > > > > > > > Hey, I know that guy! :-) > > > > > > Another userland implementation is in the > > > 'ock/reflector-aware-attributes' package. > > > https://github.com/ock-php/reflector-aware-attributes (I created t= hat one) > > > This supports both a setter method and getting the target reflector > > > from the attribute constructor. > > > > > > The problem with any userland implementation is that it only works= if > > > the attribute is instantiated (or processed) using that userland > > > library. > > > Simply calling $reflector->getAttributes()[0]->newInstance() would > > > either return an instance that is incomplete, or it would break, if > > > the attribute class expects access to its target. > > > > > > > > > I am unsurprisingly in favor of finding a solution here, as there = are innumerable cases where you need the reflectable that the attribute = is on; the most common for me is using the name/type of a property as de= faults for the attribute. > > > > > > However, I am very skeptical about a stateful global value as the = solution. We've tried very hard to remove those from PHP, mostly succes= sfully. Adding another one back in feels like a major step backwards, a= nd a great place for weird bugs to hide. > > > > > > A setter method injection is what I did in AttributeUtils, because= it was the only real option. Alternatively, I suppose core could use p= roperty setter injection (either a magically named property like $__refl= ector, or a property that itself has an attribute on it, etc.). That wo= uld allow it to be set before the constructor is called, and with proper= ty hooks would allow processing either immediately or later in the const= ructor. The downside here is that Attribute are, generally, serializabl= e, but a Reflection object is not. So if someone wanted a serializable = attribute they would have to accept the property, use it, and then remem= ber to unset it at some point. That's clumsy. > > > > > > --Larry Garfield > > > > > > > > > As someone that's written yet another userland "solution" for this= problem, I have an alternative solution, based somewhat on an internali= sed concept of "never store Reflectors". > > > > > > Introduce an interface "ReflectorAttribute" (bike shedding to come= ); which accepts a single Reflector argument. > > > > > > If the attribute implements the interface, the method is called im= mediately following instantiation. > > > > > > > > > Yep, this is the "method injection" mentioned by Larry, or what I > > > referred to as "setter injection". > > > I have not seen your library, but I assume that's where it is goin= g. > > > > > > > > > Hi Andreas, > > > > > > I guess the key difference I wanted to highlight is that the exist= ing discussion keeps referencing it as a "setter" - which I think from u= ser land at least will generally be understood to mean setting a propert= y on an object - which then adapted into Larry's mention of specifically= setting a property before the constructor is run. > > > > I guess the main reason it "keeps" doing that is that an email is not > > a wiki page that could be updated :) > > I am happy to use different terminology in an RFC. > > (with the current plan, it would only be mentioned under "alternativ= es > > that were considered") > > "method injection" seems fine. > > > > But then how would we name such a method? > > In Larry's library it is ->fromReflection(..), but this is something= I > > would typically use for static factories. > > To me, ->setReflector() is still ok even if internally it is not a > > setter. The method describes the contract, not what happens inside. > > Another idea would be ->tellAboutReflector() or maybe ->injectTarget= Reflector()? > > > > > > > > I think it's a bad idea to reference this concept as "setting a pr= operty" - my understanding is that it's never a good idea to hang onto R= eflector objects longer than absolutely necessary, so I don't think this= feature should then result in people doing that due to the impression i= t gives (i.e. if it was referred to as "setReflection()" or if = the description for it is "allows an Attribute to store the Reflector ta= rget it was declared on" etc) > > > > > > > > > -------- > > > > Now, to resolve the controversial part of this discussion. > > > > We could reduce the RFC to the uncontroversial part: > > Provide a ReflectionAttribute->getTargetReflector(). > > > > With this, the rest of the proposal can be implemented in userland > > using debug_backtrace(). > > https://3v4l.org/Ilrqm#vnull > > > > #[Attribute] > > class MyAttribute { > > public function __construct() { > > $target_reflector =3D > > debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | > > DEBUG_BACKTRACE_PROVIDE_OBJECT, 3)[1]['object']; > > } > > } > > > > Yes it feels dirty, but now it is now longer something we have to > > argue about in this list :) > > > > > > Why do we have to call a constructor before we initialize a property= ? https://3v4l.org/srdM6 > > > > You can do this in regular php, but it is even simpler in the engine. > > > > =E2=80=94 Rob >=20 > This is interesting, but I still add some logistical clutter to the > attribute class. > It does bring some advantage over post-construction method injection, > because you can do the logistics in a trait, and then in the > constructor you have all the information available. > But, even if that part is hidden away in the engine, now we have a > property that we probably want to unset later. >=20 > -- Andreas >=20 I haven=E2=80=99t read the entire thread yet, but why would you want to = unset it? In my experience of working with attributes, they have a very = short lifetime (usually to the end of the loop/function, and no more) si= nce they=E2=80=99re just metadata. The biggest boon I see here is the ab= ility to easily encapsulate some logic in my attributes without relying = on 3rd party behavior. If some library decides to keep them around, I wi= ll assume they know what they=E2=80=99re doing. =E2=80=94 Rob --e6b9c2f0ecf34137ae3663b151b2718f Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable


On Sat, Jul 5, 2025, at 00:47, Andreas Hennings wrote:=
On Sat, 5 Jul = 2025 at 00:11, Rob Landers <rob@= bottled.codes> wrote:
>
>
>= ;
> On Fri, Jul 4, 2025, at 17:21, Andreas Hennings wrote:<= /div>
>
> On Fri, 4 Jul 2025 at 06:30, Stephen Reay = <php-lists@koalephant.com= > wrote:
> >
> >
> &= gt;
> > On 4 Jul 2025, at 00:54, Andreas Hennings <andreas@dqxtech.net> wrote:<= /div>
> >
> > On Thu, 3 Jul 2025 at 19:17, Ste= phen Reay <php-lists@koal= ephant.com> wrote:
> >
> >
<= div>> >
> >
> >
> >= ; Sent from my iPhone
> >
> > On 3 Jul 2= 025, at 23:40, Larry Garfield <larry@garfieldtech.com> wrote:
> >
= > > =EF=BB=BFOn Wed, Jul 2, 2025, at 5:26 PM, Andreas Hennings wro= te:
> >
> > This topic was discussed in = the past as "Declaration-aware
> > attributes", and ment= ioned in the discussion to "Amendments to
> > Attributes= ".
> > I now want to propose a close-to-RFC iteration of= this.
> > (I don't have RFC Karma, my wiki account is "= Andreas Hennings (donquixote)")
> >
> > = -----
> >
> > Primary proposal
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> >
> > I propose to introduce 3 new methods on ReflectionAtt= ribute.
> >
> > static ReflectionAttribu= te::getCurrentTargetReflector(): ?Reflector
> > Most of = the time, this will return NULL.
> > During the executio= n of ReflectionAttribute->newInstance(), it will
> > = return the reflector of the symbol on which the attribute is found.
> > (in other words, during
> > $reflector-&= gt;getAttributes()[$i]->newInstance(), it will return
> = > $reflector.)
> > During the execution of
= > > ReflectionAttribute::invokeWithTargetAttribute($target, $callb= ack), it
> > will return $target.
> > If= the call stack contains multiple calls to the above mentioned
> > methods, only the closest/deepest one counts.
> = > (This means that php needs to maintain a stack of reflectors.)
> >
> >
> > *snip*
> >
> > Other alternatives
> > =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> >
> > In older discussions, it was suggested t= o provide the target reflector
> > as a special construc= tor parameter.
> > This is problematic because an attrib= ute expression #[MyAttribute('a',
> > 'b', 'c')] expects= to pass values to all the parameters.
> >
>= ; > Another idea was to provide the target reflector through a kind o= f
> > setter method on the attribute class.
&g= t; > This can work, but it makes attribute classes harder to write, b= ecause
> > the constructor does not have all the informa= tion.
> > It may also prevent attribute classes from bei= ng stateless (depending
> > how we define stateless).
> >
> >
> > Userland imple= mentations
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> >
> >= ; One userland implementation that was mentioned in this list in the
> > past is in the 'crell/attributeutils' package.
> > This one uses a kind of setter injection for the target refl= ector.
> > See
> >
> >
> &= gt; Hey, I know that guy! :-)
> >
> > An= other userland implementation is in the
> > 'ock/reflect= or-aware-attributes' package.
> &= gt; This supports both a setter method and getting the target reflector<= /div>
> > from the attribute constructor.
> ><= /div>
> > The problem with any userland implementation is that= it only works if
> > the attribute is instantiated (or = processed) using that userland
> > library.
&g= t; > Simply calling $reflector->getAttributes()[0]->newInstance= () would
> > either return an instance that is incomplet= e, or it would break, if
> > the attribute class expects= access to its target.
> >
> >
> > I am unsurprisingly in favor of finding a solution here, as t= here are innumerable cases where you need the reflectable that the attri= bute is on; the most common for me is using the name/type of a property = as defaults for the attribute.
> >
> > H= owever, I am very skeptical about a stateful global value as the solutio= n.  We've tried very hard to remove those from PHP, mostly successf= ully.  Adding another one back in feels like a major step backwards= , and a great place for weird bugs to hide.
> >
> > A setter method injection is what I did in AttributeUtils, b= ecause it was the only real option.  Alternatively, I suppose core = could use property setter injection (either a magically named property l= ike $__reflector, or a property that itself has an attribute on it, etc.= ).  That would allow it to be set before the constructor is called,= and with property hooks would allow processing either immediately or la= ter in the constructor.  The downside here is that Attribute are, g= enerally, serializable, but a Reflection object is not.  So if some= one wanted a serializable attribute they would have to accept the proper= ty, use it, and then remember to unset it at some point.  That's cl= umsy.
> >
> > --Larry Garfield
> >
> >
> > As someone that's wri= tten yet another userland "solution" for this problem, I have an alterna= tive solution, based somewhat on an internalised  concept of "never= store Reflectors".
> >
> > Introduce an= interface "ReflectorAttribute" (bike shedding to come); which accepts a= single Reflector argument.
> >
> > If t= he attribute implements the interface, the method is called immediately = following instantiation.
> >
> >
> > Yep, this is the "method injection" mentioned by Larry, or = what I
> > referred to as "setter injection".
= > > I have not seen your library, but I assume that's where it is = going.
> >
> >
> > Hi An= dreas,
> >
> > I guess the key differenc= e I wanted to highlight is that the existing discussion keeps referencin= g it as a "setter" - which I think from user land at least will generall= y be understood to mean setting a property on an object - which then ada= pted into Larry's mention of specifically setting a property before the = constructor is run.
>
> I guess the main reaso= n it "keeps" doing that is that an email is not
> a wiki pa= ge that could be updated :)
> I am happy to use different t= erminology in an RFC.
> (with the current plan, it would on= ly be mentioned under "alternatives
> that were considered"= )
> "method injection" seems fine.
>
> But then how would we name such a method?
> In Larry'= s library it is ->fromReflection(..), but this is something I
> would typically use for static factories.
> To me, = ->setReflector() is still ok even if internally it is not a
> setter. The method describes the contract, not what happens inside= .
> Another idea would be ->tellAboutReflector() or mayb= e ->injectTargetReflector()?
>
> >
=
> > I think it's a bad idea to reference this concept as "set= ting a property" - my understanding is that it's never a good idea to ha= ng onto Reflector objects longer than absolutely necessary, so I don't t= hink this feature should then result in people doing that due to the imp= ression it gives (i.e. if it was referred to as "setReflection<subtyp= e>()" or if the description for it is "allows an Attribute to store t= he Reflector target it was declared on" etc)
> >
>
>
> --------
>
= > Now, to resolve the controversial part of this discussion.
>
> We could reduce the RFC to the uncontroversial par= t:
> Provide a ReflectionAttribute->getTargetReflector()= .
>
> With this, the rest of the proposal can = be implemented in userland
> using debug_backtrace().
=
>
> #[Attribute]
&g= t; class MyAttribute {
>     public fun= ction __construct() {
>      =    $target_reflector =3D
> debug_backtrace(DEBUG_= BACKTRACE_IGNORE_ARGS |
> DEBUG_BACKTRACE_PROVIDE_OBJECT, 3= )[1]['object'];
>     }
> = }
>
> Yes it feels dirty, but now it is now lo= nger something we have to
> argue about in this list :)
>
>
> Why do we have to call a const= ructor before we initialize a property? https://3v4l.org/srdM6
>
> You can= do this in regular php, but it is even simpler in the engine.
>
> =E2=80=94 Rob

This is inte= resting, but I still add some logistical clutter to the
attrib= ute class.
It does bring some advantage over post-construction= method injection,
because you can do the logistics in a trait= , and then in the
constructor you have all the information ava= ilable.
But, even if that part is hidden away in the engine, n= ow we have a
property that we probably want to unset later.

-- Andreas

=
I haven=E2=80=99t read the entire thread yet, but why wou= ld you want to unset it? In my experience of working with attributes, th= ey have a very short lifetime (usually to the end of the loop/function, = and no more) since they=E2=80=99re just metadata. The biggest boon I see= here is the ability to easily encapsulate some logic in my attributes w= ithout relying on 3rd party behavior. If some library decides to keep th= em around, I will assume they know what they=E2=80=99re doing.

=E2=80=94 Rob
--e6b9c2f0ecf34137ae3663b151b2718f--