Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:119067 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 76406 invoked from network); 1 Dec 2022 01:38:41 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 1 Dec 2022 01:38:41 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 5C3EC180087 for ; Wed, 30 Nov 2022 17:38:38 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS17378 206.123.64.0/18 X-Spam-Virus: No X-Envelope-From: Received: from mail1.25mail.st (mail1.25mail.st [206.123.115.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 30 Nov 2022 17:38:37 -0800 (PST) Received: from smtpclient.apple (unknown [49.48.240.15]) by mail1.25mail.st (Postfix) with ESMTPSA id 221BA60664; Thu, 1 Dec 2022 01:38:30 +0000 (UTC) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.1\)) Date: Thu, 1 Dec 2022 08:38:27 +0700 References: <0854b030-c51c-4c1b-a7dd-22835a1e5da9@app.fastmail.com> <831b9906-dc0c-420c-b22f-8a0cc8a1ad64@app.fastmail.com> <434BDABD-8551-46C8-98EC-8CA87952AE25@gmail.com> <29f2a6a5-08f7-4abb-965f-56bb1cc49565@app.fastmail.com> To: Larry Garfield , php internals In-Reply-To: <29f2a6a5-08f7-4abb-965f-56bb1cc49565@app.fastmail.com> Message-ID: X-Mailer: Apple Mail (2.3696.120.41.1.1) Subject: Re: [PHP-DEV] [RFC] Asymmetric Visibility, with readonly From: php-lists@koalephant.com (Stephen Reay) > On 30 Nov 2022, at 22:09, Larry Garfield = wrote: >=20 > On Tue, Nov 29, 2022, at 11:25 PM, Stephen Reay wrote: >=20 >> Hi Larry, >>=20 >> Thank you for clarifying the setter behaviour in more explicit terms,=20= >> but I have to say I=E2=80=99m quite disappointed in this continued = =E2=80=9Cuse the=20 >> logic of readonly to apply to something that is explicitly not=20 >> readonly=E2=80=9D - this is even more stark now that you=E2=80=99ve = explicitly made=20 >> them mutually exclusive behaviours. >>=20 >> I=E2=80=99m generally very in favour of maintaining consistency, but = this seems=20 >> like it=E2=80=99s using technical consistency as an excuse to justify=20= >> unintuitive behaviour that breaks consistency in another, much more=20= >> obvious way. >>=20 >>=20 >> Can you explain why it makes more sense to maintain consistency with=20= >> =E2=80=9Creadonly=E2=80=9D than it does to maintain consistency with = the existing=20 >> =E2=80=9C__set()=E2=80=9D behaviour for properties, particularly now = that you=E2=80=99ve=20 >> indicated these features (asymmetric visibility and readonly) are=20 >> mutually exclusive?=20 >>=20 >> While it=E2=80=99s stated multiple times that =E2=80=9Creadonly=E2=80=9D= introduced a limited=20 >> form of asymmetric visibility, and thus this is a continuation, in=20 >> terms of intuitiveness, the existing __set() rules are very easy to=20= >> comprehend even with readonly: >>=20 >> - if the property is declared as public, __set() is never called; if=20= >> it=E2=80=99s declared as protected, __set is called when the property = is=20 >> accessed from outside that class or it=E2=80=99s hierarchy. Yes, I = know that=20 >> readonly imposes an implicit visibility difference - but that is=20 >> essentially an implementation detail, from the point of view of the=20= >> userland developer, it=E2=80=99s not a clear statement of intended = behaviour on=20 >> their part, expressed through the code as written. >>=20 >> For example, with `public readonly int $foo` it=E2=80=99s quite = obvious why=20 >> __set() isn=E2=80=99t called, using the exiting well-understood = logic: it=E2=80=99s a=20 >> public property. PHP applies a kind of asymmetric visibility to the=20= >> property behind the scenes, but that isn=E2=80=99t what the developer = declared,=20 >> it=E2=80=99s the implementation. This behaviour matches that of = regular,=20 >> non-readonly fields: when the field is declared public (or has = implicit=20 >> public visibility) __set() is never called. >>=20 >> If we make that field protected, __set() will be called when the=20 >> property is written to from outside the class, regardless of whether=20= >> it=E2=80=99s readonly or not. >>=20 >>=20 >> What you=E2=80=99re proposing changes that, in a way that is = completely=20 >> unintuitive: when attempting to *write* data to a property that is=20 >> marked as protected(set), the __set() method will not be called. >>=20 >>=20 >> So please, can you explain to me why consistency with an = implementation=20 >> detail of readonly properties is more important than consistency with=20= >> declared developer intention for regular properties via the magic=20 >> setter method? >=20 > There's a couple of reasons. >=20 > One, and arguably the most important, readonly and aviz being = incompatible is, hopefully, a temporary situation. There's some fiddly = bits to work out design-wise, and based on earlier comments in the = thread we're going to punt on that for now to avoid that dragging down = the whole RFC. I believe we absolutely should allow them together in = the future (maybe in a later 8.3 RFC, maybe a future version, TBD), = which means ensuring, now, that they are compatible in the future. This = approach involves the fewest future BC breaks. >=20 > Second, I wouldn't call the current behavior of readonly a mere = implementation detail. It's weird and unexpected, I'd agree, but only = as a side effect of previous design decisions, some of which are even = older than readonly. But it's an observed behavior that code can rely = on, and in some cases does. For example: >=20 > = https://peakd.com/hive-168588/@crell/php-tricks-lazy-public-readonly-prope= rties >=20 > The "unset a declared property to force it through __get once" is a = trick that some ORMs use extensively. readonly just inherited that, = leading to the current behavior: __set depends on the write/set = visibility of the property and its settedness. This RFC doesn't change = anything there. =20 >=20 > The alternative would be to have __set called always for a = non-public-set property. However, that is a place for bugs, as you then = can't not have a back-door way to publicly set a property even if it's = declared private(set). (Or, you have to be very careful in your __set = to avoid it.) That is both inconsistent with the language today, and = error prone. >=20 > Finally, we're planning to work in the near-future on property hooks = (aka property accessors), which would allow per-property custom set = routines. That would largely remove the issue entirely, as the use of = __set would go way down and you'd basically never have to use it with a = declared property, fancy tricks or no, so this issue would never come up = at all. >=20 > --Larry Garfield >=20 > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php Hi Larry, I think there must be some confusion somewhere, based on some of your = comments. I=E2=80=99m not suggesting that the =E2=80=9Cunset to force a **public** = property to go through getter/setter methods=E2=80=9D logic should be = specifically different. I=E2=80=99m suggesting that when the decision is made to call __set or = not, the properties **set** visibility is what should be considered, not = it=E2=80=99s **get** visibility. Your own comment even describes this behaviour: "leading to the current = behavior: __set depends on the write/set visibility of the property" But your RFC says that __set will depend on the **read/get** visibility = of the property. > you then can't not have a back-door way to publicly set a property = even if it's declared private(set). (Or, you have to be very careful in = your __set to avoid it.) That is both inconsistent with the language = today, and error prone. If a developer adds a _set() method that can write to a private(set) = property, I would expect that is working exactly as desired, exactly as = it does **now** where it=E2=80=99s just a =E2=80=9Cprotected=E2=80=9D = property. > we're planning to work in the near-future on property hooks That=E2=80=99s great, but I don=E2=80=99t think weird unintuitive = behaviour should be added because =E2=80=9Cwell we=E2=80=99re gonna try = and solve this through something else later=E2=80=9D Cheers Stephen=20