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