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