On Wed, Mar 12, 2025, at 11:10, Rob Landers wrote: > On Thu, Mar 6, 2025, at 00:11, Rob Landers wrote: >> Hello PHP Internals, >> >> I'd like to introduce my RFC for discussion: >> https://wiki.php.net/rfc/short-and-inner-classes >> >> This RFC defines a short class syntax as well as the ability to nest classes >> inside another class. This introduces an unprecedented amount of control, >> flexibility, and expressiveness over how objects are used and instantiated >> in PHP. There is a PR (https://github.com/php/php-src/pull/17895) that >> implements this functionality -- all test failures are related to >> different/new/incorrect error messages being generated. However, the core >> functionality exists to take for a test ride. >> >> So, what do I mean by "unprecedented amount of control"? With this change, >> you can declare an inner class as private or protected, preventing its usage >> outside of the outer class: >> >> class User { >> private class Id {} >> >> public function __construct(public self::Id $id) {} >> } >> >> In the above example, the class `User` is impossible to construct even >> though it has a public constructor (except through reflection) because >> User::Id is private; User::Id cannot be instantiated, used as a type hint, >> or even via `instanceof` outside of the User class itself. This example >> isn't practical but demonstrates something that is nearly impossible in >> previous versions of PHP, where all classes are essentially publicly >> accessible from anywhere within the codebase. >> >> As a number of inner classes will probably be used as DTOs, the RFC >> introduces a "short syntax" for declaring classes, which enhances >> expressiveness, even allowing the usage of traits, all in a single line: >> >> // declare a readonly Point, that implements Vector2 and uses the Evolvable >> trait >> readonly class Point(public int $x, public int $y) implements Vector2 use >> Evolvable; >> >> When combined with inner classes, it looks something like this: >> >> class Pixel { >> public readonly class Point(public int $x, public int $y) implements >> Vector2 use Evolvable; >> } >> >> // Create a new pixel point with property $x and $y set to 0 >> $p = new Pixel::Point(0, 0); >> >> There are far more details in the RFC itself, so please check it out. I'm >> quite excited to hear your thoughts! >> >> — Rob >> >> PS. I know I tend to rush into things, but I want to make it clear that I'm >> not rushing this -- I've learned from my mistakes (thank you to those who >> have given me advice). I'm going to do this right. >> >> > > Hello internals, > > I've made some major updates to the text of the RFC to clarify behaviors and > revisited the implementation (which is still under development, though I hope > to have a draft by the end of this weekend). Here's a broad overview of what > has changed in inner classes: > > - Accessing inner classes is done via a new token: ":>" instead of "::". > - Inner classes may now be infinitely nested. > - Inner classes may be declared `abstract`. > - Documented changes to ReflectionClass. > - Usage of `static` to refer to inner classes is restricted to prevent > accidental violations of LSP. > > Otherwise, there are not any big changes, but a lot of time was spent > clarifying behavior and expanding on the reasoning for those decisions in the > RFC itself. > > — Rob
For those who are interested, I've opened the PR that enables this feature: https://github.com/php/php-src/pull/18069 — Rob