Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128102 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 EA9131A00BC for ; Fri, 18 Jul 2025 12:10:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1752840550; bh=yHrPZyVTDGztPMU6l4hVca8waWvs3Y0f6hF72Gk+pBw=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=VR6Zl3Ap0NcjZgXs1FmPPfWUOi2kigh+ju8lY9GQ6A1Dcw4w6Uq6AuLdUeMWYq+C4 N0hIGFONdikrLYdkt02bz32eBIFX800L8r4DayF3YcXoOJPL0ZStoT2f6Slj9v1AdT ttv98z+/XUswusWzMuRYQxoMf59aBE1WeiMbBm3+WqrIJZ4jyt/Z+2Hjv3zhXMiMIh z2ZqDixoAmytjPF7C3v7QgvjNPGzmqX8OxlXff3VbZTcGgy+9PRYXqRg6LA+1JiZIa m8Zj2trYY7tVXpFxdZq99U8lY+f5hwNS64aORekgCutUPTR7PgFQCt6hipucncrVBD So3cdxUEHWQuQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A7CD91801FD for ; Fri, 18 Jul 2025 12:09:08 +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.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_NONE, 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 chrono.xqk7.com (chrono.xqk7.com [176.9.45.72]) (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 12:09:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bastelstu.be; s=mail20171119; t=1752840650; bh=XY6GORIPXsfl9FB4qyoM+Y22KsPiADpSimVjWYzmgfM=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type:from:to:cc:subject:message-id; b=dZtGzsx50QB4TQ9EFUFnw5m7mIEMDVUrgCLMnIPwKfXGzbNsUl+SXU5nE/Z3IPKcC ph89k5BlR2W173moDOKmKURElZP/XQMlHiMDtzasT2vaIaL6xlrDFaV7qNutZ7dZrW j6aDjon1HWtnOuWde8a/s/KhZoNkyQwW/h2iLBCDC5L9wyVjUi6RqlChif0Tj2jrUH jGJ7v1jzMDpwL/9VfG8Luja2WE3R3xIQnqfmTNJJGdUsvEsM0JmYH8bdNPmNqsAprd zuo2fmHjQ3TRu8xpOhOi7EXcaVU7ZXxvyrsYZBUzIj5OtOnD/ZBu51Kj/QH1kcFZk/ 9guuDNGWbRokw== Message-ID: <96e0ea70-291e-4f0a-b449-acbaef16c099@bastelstu.be> Date: Fri, 18 Jul 2025 14:10:48 +0200 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Subject: Re: [PHP-DEV] [RFC] Readonly property hooks To: Nick Cc: Larry Garfield , php internals References: <1e8634d7-ac1a-4025-b4e2-1948aabf5251@app.fastmail.com> <13B58381-AA61-4D38-A688-DD9E367ADE6F@nicksdot.dev> Content-Language: en-US In-Reply-To: <13B58381-AA61-4D38-A688-DD9E367ADE6F@nicksdot.dev> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: tim@bastelstu.be (=?UTF-8?Q?Tim_D=C3=BCsterhus?=) Hi Apologies for the belated reply. I was busy with getting my own implementation wrapped up and the thread was so active that I had troubles keeping up. On 7/11/25 06:20, Nick wrote: > Personally, I would really like to have `get` hooks on readonly properties. Please consider something like this: > > ```php > readonly class Foo > { > public function __construct( > public Output $style, > public string $some { > get => Output::One === $this->style ? ucfirst($this->some) : strtoupper($this->some); > set => '' !== $value ? $value : throw new \Exception(); > } > ) {} > } > ``` > > Easy-to-digest one-liners. Concerns remain separated. Set takes care of validation, get formats. I respectfully disagree on the "easy-to-digest" part. A 98 character line containing logic is not easy to digest. > If `get` would not be allowed, we couldn’t do such an obvious thing. For what reason? In *this specific instance* the `get` hook would not violate my expectations, but this is not true in general. > Instead we would need to delegate formatting to the `set` hook which is messy. Running formatting for every access is messy. And it's messy to needlessly use hooks for something that can just be constructor logic. Since `$some` is *always* assigned when running the constructor, this can just be: readonly class Foo { public string $some; public function __construct( public Output $style, string $some, ) { if ($some === '') { throw new \Exception(); } $this->some = match ($style) { Output::One => ucfirst($some), default => strtoupper($some), }; } } Making `Foo` a plain old data class without any behavior after construction and with very obvious control flow within the constructor. This results in both more efficient and easier to reason about code. Best regards Tim Düsterhus