Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128115 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 C55A81A00BC for ; Fri, 18 Jul 2025 15:50:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1752853695; bh=3RZZLEurEv3XAWzxv3pLIVjn2Ps1sU8Lbd0Sl0wDNC4=; h=Date:From:To:In-Reply-To:References:Subject:From; b=aEQSGPitpWg0f3gUWqpF0TxpIuuJx0TiYQ/Bgrh7xSdkmlJz1VUJtVBXaQx8TGnw0 FXrMa3NYusQGll3rEGqwXoheb4CB+jjyJzLc8vYC6VxcGBl/0kp9qfYYCI9g3OKZYS fXoMZVCg01qGN3c/naH2Vke2y56hSZyhbgWI8+JDqEkHSgk4voURfQPP+2Ep2/E8Vo wxGa1/IOCjMNaP90uAgKmQLreAM/EQiw5hQkreGftr9B9QoKBKb7gsLDdBFqrA7+JS gvMeF2sG/UIb+J/jiXHVxvKBTQLFSPRRR6VNrxQukuBVovbhISnC3r6k69tZUKve+6 D1vyBdT1uBxpQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id CB7C6180083 for ; Fri, 18 Jul 2025 15:48:14 +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-b7-smtp.messagingengine.com (fhigh-b7-smtp.messagingengine.com [202.12.124.158]) (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, 18 Jul 2025 15:48:14 +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 13B177A0089; Fri, 18 Jul 2025 11:50:00 -0400 (EDT) Received: from phl-imap-05 ([10.202.2.95]) by phl-compute-05.internal (MEProxy); Fri, 18 Jul 2025 11:50:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=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=1752853799; x=1752940199; bh=L9GKkHCl3y mpcu+13YVS+k2KtNJpLtBHkjoIlAKPV2w=; b=ikB8TEPHFO0vPp/2tRRX/ZOThY KxgaZDolo0yb322xGK8pxhE1ndDNprFCPyJrX3a8UaO1Ha0ZwkOQZfGwRlsjzC3/ 70/3uoT5iBhyNvgdeBwgEY0tAmscvb8CbQ1oi2Qq9+aS/45mbkM/oREhqNFvlnCW KL5JzZX8olwtBf/lkx9rd1eij58VePmmaozUtAcn36HasFF70fxvfYlbHgoDar5z /B8Px88VXoVnFJD0PMjc+1FE+o93+EUzI7PFkemop2sia/4SDsdBS4DoLKJbr+ke VXktxSKT1CWrnJbe2nVcQy12UOdYB0Y6b42PnPLnh4qaHGWWeSt4tmacdU9A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=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= 1752853799; x=1752940199; bh=L9GKkHCl3ympcu+13YVS+k2KtNJpLtBHkjo IlAKPV2w=; b=nBgXCkog2lg7ZazerX7yeREt/h2hHY33x0N0jJD0U+Ttnnbzat3 whE8dlkFjzPMKho/c8pb03JzxBtOaJUzE/95oHHivbfk3w5UcnJNsdmweDJRFzss dxPPxVbqw9n7qR1eC8MXEJqx55SVb2a6KaIbzxUhkJe7PBwXeDC/QFsfd3t92sK+ EKZLd7QgkGf3w8uy+u/8jg7Kl/Wjh/vVXmWvdd5pPGQX8p08EA2cWdWHxDxw0W5y /rsH4182Q53F1SN1SXxvxLjblhPCQ1W/QZf0m2++DFRyayb5qSK2SHx/Xg31h98r jt9dnq3/dsASy15LlqcmvO4y/Q4zMSRtcqA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgdeifeekjecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjug hrpefoggffhffvkfgjfhfutgesrgdtreerredtjeenucfhrhhomhepfdftohgsucfnrghn uggvrhhsfdcuoehrohgssegsohhtthhlvggurdgtohguvghsqeenucggtffrrghtthgvrh hnpedtueejtdethfeulefhtdelieduteelffdtudelheffgedtieehhfelieejgfevgeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehrohgsse gsohhtthhlvggurdgtohguvghspdhnsggprhgtphhtthhopeefpdhmohguvgepshhmthhp ohhuthdprhgtphhtthhopehtihhmsegsrghsthgvlhhsthhurdgsvgdprhgtphhtthhope hlrghrrhihsehgrghrfhhivghlughtvggthhdrtghomhdprhgtphhtthhopehinhhtvghr nhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 1DF3F1820074; Fri, 18 Jul 2025 11:49:59 -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: T5f4527d1a0d4de24 Date: Fri, 18 Jul 2025 17:49:38 +0200 To: =?UTF-8?Q?Tim_D=C3=BCsterhus?= , "Larry Garfield" , "php internals" Message-ID: <0d9a2968-26dd-43dd-9733-d2eb621ab9ec@app.fastmail.com> In-Reply-To: <2641b8bc-6337-4b75-a5a3-93dee1b03796@bastelstu.be> References: <1e8634d7-ac1a-4025-b4e2-1948aabf5251@app.fastmail.com> <9D5043B2-1589-4FD5-B289-6E98FB1177BE@nicksdot.dev> <0856c89f-2000-448a-bbbf-c145a8699f6a@app.fastmail.com> <2641b8bc-6337-4b75-a5a3-93dee1b03796@bastelstu.be> Subject: Re: [PHP-DEV] [RFC] Readonly property hooks Content-Type: multipart/alternative; boundary=95102c3e917842f48531ca5180ac48c3 From: rob@bottled.codes ("Rob Landers") --95102c3e917842f48531ca5180ac48c3 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Fri, Jul 18, 2025, at 17:25, Tim D=C3=BCsterhus wrote: > Hi >=20 > On 7/14/25 15:38, Larry Garfield wrote: > > Thanks, Ilija. You expressed my concerns as well. And yes, in prac= tice, readonly classes over-reaching is the main use case; if you're mar= king individual properties readonly, then just don't mark the one that h= as a hook on it (use aviz if needed) and there's no issue. >=20 > A readonly class is not just a convenience shortcut to mark each=20 > individual property as readonly. It has important semantics of its own= ,=20 > because it forces child classes to also be readonly. And even for fina= l=20 > classes it communicates to the user that "I won't be adding non-readon= ly=20 > properties to the class". Wasn=E2=80=99t that the entire point of readonly classes? Because it was= painful to write readonly for every property. Then if a property is rea= donly, the inherited property is also readonly, so, by extension: a clas= s extending a readonly class is also readonly. There=E2=80=99s no =E2=80=9Ccommunication=E2=80=9D here; just logic.=20 >=20 > Marking a class as readonly must therefore be a deliberate decision,=20 > since it affects the public API of your class and in turn also user=20 > expectations. Not really. I can remove the readonly designation and manually mark ever= y property as readonly. The behavior of the class doesn=E2=80=99t magica= lly change. Or, at least, I hope it doesn=E2=80=99t.=20 >=20 > > Perhaps we're thinking about this the wrong way, though? So far we'= ve talked as though readonly makes the property write-once. But... what= if we think of it as applying to the field, aka the backing value? >=20 > I think of readonly from the view of the public API surface of an=20 > object. The property hooks RFC was very explicit in that property hook= s=20 > are intended to be =E2=80=9Ctransparent to the user=E2=80=9D and can b= e added without=20 > breaking the public API. In other words: Whether or not a property is=20 > implemented using a hook should be considered an implementation detail=20 > and as a user of a class I do not care whether there is a backing valu= e=20 > or not. >=20 > > So readonly doesn't limit calling the get hook, or even the set hook= , multiple times. Only writing to the actual value in the object table.= That gives the exact same set of guarantees that a getX()/setX() metho= d would give. The methods can be called any number of times, but the st= ored value can only be written once. >=20 > As a user of a class the "backing table" is mostly inaccessible to me=20 > when interacting with objects. It's only exposed via var_dump() and=20 > serialize(), the former of which is a debug functionality and the outp= ut=20 > of latter not something I must touch. >=20 > > It would not guarantee $foo->bar =3D=3D=3D $foo->bar in all cases (t= hough that would likely hold in the 99% case in practice), but then, $fo= o->getBar() =3D=3D=3D $foo->getBar() has never been guaranteed either. >=20 > Properties and methods are something different. For methods there a=20 > reasonable expectation that *behavior* is associated with them, for=20 > properties there is not. Unless I missed something. Hooks are fancy methods? There is nothing int= rinsic about object properties. There is nothing that says two calls to = the same property=E2=80=99s getters are going to result in the same valu= es. There is asynchronous php, declare ticks, etc. especially in the cas= e of globals, there is no guarantee you even have the same object. At th= e end of the day, it is up to the programmer building that system / prog= ram to provide those guarantees=E2=80=94 not the language.=20 >=20 > A 99% case is not sufficient for me to rely on when there's explicit=20 > communication by the class author that I may rely on properties not=20 > suddenly changing. >=20 > Best regards > Tim D=C3=BCsterhus >=20 =E2=80=94 Rob --95102c3e917842f48531ca5180ac48c3 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable


On Fri, Jul 18, 2025, at 17:25, Tim D=C3=BCsterhus wro= te:
Hi

On 7/14/25 15:38, Larry Garfield wrote:
> = Thanks, Ilija.  You expressed my concerns as well.  And yes, i= n practice, readonly classes over-reaching is the main use case; if you'= re marking individual properties readonly, then just don't mark the one = that has a hook on it (use aviz if needed) and there's no issue.

A readonly class is not just a convenience shortcut to= mark each 
individual property as readonly. It has impor= tant semantics of its own, 
because it forces child class= es to also be readonly. And even for final 
classes it co= mmunicates to the user that "I won't be adding non-readonly 
<= div>properties to the class".

Wasn= =E2=80=99t that the entire point of readonly classes? Because it was pai= nful to write readonly for every property. Then if a property is readonl= y, the inherited property is also readonly, so, by extension: a class ex= tending a readonly class is also readonly.

Ther= e=E2=80=99s no =E2=80=9Ccommunication=E2=80=9D here; just logic. 

<= br>
Marking a class as readonly must therefore be a deliberate= decision, 
since it affects the public API of your class= and in turn also user 
expectations.
<= div>
Not really. I can remove the readonly designation and= manually mark every property as readonly. The behavior of the class doe= sn=E2=80=99t magically change. Or, at least, I hope it doesn=E2=80=99t.&= nbsp;


> Perhaps we're thinking about this the wrong wa= y, though?  So far we've talked as though readonly makes the proper= ty write-once.  But... what if we think of it as applying to the fi= eld, aka the backing value?

I think of readonly= from the view of the public API surface of an 
object. T= he property hooks RFC was very explicit in that property hooks 
are intended to be =E2=80=9Ctransparent to the user=E2=80=9D and = can be added without 
breaking the public API. In other w= ords: Whether or not a property is 
implemented using a h= ook should be considered an implementation detail 
and as= a user of a class I do not care whether there is a backing value <= /div>
or not.

> So readonly doesn't limi= t calling the get hook, or even the set hook, multiple times.  Only= writing to the actual value in the object table.  That gives the e= xact same set of guarantees that a getX()/setX() method would give. = ; The methods can be called any number of times, but the stored value ca= n only be written once.

As a user of a class th= e "backing table" is mostly inaccessible to me 
when inte= racting with objects. It's only exposed via var_dump() and 
serialize(), the former of which is a debug functionality and the out= put 
of latter not something I must touch.

=
> It would not guarantee $foo->bar =3D=3D=3D $foo->b= ar in all cases (though that would likely hold in the 99% case in practi= ce), but then, $foo->getBar() =3D=3D=3D $foo->getBar() has never b= een guaranteed either.

Properties and methods a= re something different. For methods there a 
reasonable e= xpectation that *behavior* is associated with them, for 
= properties there is not.

Unless I = missed something. Hooks are fancy methods? There is nothing intrinsic ab= out object properties. There is nothing that says two calls to the same = property=E2=80=99s getters are going to result in the same values. There= is asynchronous php, declare ticks, etc. especially in the case of glob= als, there is no guarantee you even have the same object. At the end of = the day, it is up to the programmer building that system / program to pr= ovide those guarantees=E2=80=94 not the language. 


A= 99% case is not sufficient for me to rely on when there's explicit = ;
communication by the class author that I may rely on propert= ies not 
suddenly changing.

Best= regards
Tim D=C3=BCsterhus

<= div>
=E2=80=94 Rob
--95102c3e917842f48531ca5180ac48c3--