Re: [RFC] Readonly property hooks
| From: | Tim Düsterhus | Date: | Fri, 18 Jul 2025 12:10:48 +0000 |
| Subject: | Re: [RFC] Readonly property hooks | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-128102@lists.php.net to get a copy of this message | ||
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 haveI respectfully disagree on the "easy-to-digest" part. A 98 character line containing logic is not easy to digest.gethooks on readonly properties. Please consider something like this: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.
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