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

Reply via email to