This RFC from Rob Landers proposed letting you declare a class inside another class, with public, protected or private visibility just like a method. That would let you keep a helper class, like a builder or a small data object, tied to the one class that uses it. It was declined.
How it would have worked
class Outer { public class Inner { public function __construct(public string $message) {} } private class PrivateInner { public function __construct(public string $message) {} } } $foo = new Outer\Inner('Hello, world!'); echo $foo->message; // outputs: Hello, world! $baz = new Outer\PrivateInner('Hello, world!'); // Uncaught TypeError: Cannot instantiate class Outer\PrivateInner from the global scope
You refer to a nested class as Outer\Inner, so the outer class acts a bit like a namespace.
The RFC laid out these rules:
- A
privatenested class can only be used inside its outer class, aprotectedone also works in child classes, and apublicone works anywhere. - Leaving out the visibility keyword makes it
public. - Nested classes can be
readonly,finalorabstract, and the outer class's modifiers don't carry over to them. - A nested class can access the outer class's private members, but the outer class can't access the nested class's private members.
- A nested class doesn't get a reference to the outer object automatically. You pass it in if you need it.
- A public method can't declare a private nested class as its return type, which throws a
TypeError. You can return it behind an interface instead. - You can nest classes inside classes, anonymous classes, enums and interfaces, but not traits.
ReflectionClassgets a newisNestedClass()method.
What it means for existing code
The syntax is new, so it doesn't conflict with code you have today. Some error messages would change, though, so tests that assert on exact messages could fail. Tools that parse PHP, like IDEs and static analyzers, would also need updates to understand the new syntax.
The vote
The RFC was declined 2 to 20 against the two-thirds majority it needed. Voting closed on May 18, 2025.