PHP 8.3: New #[\Override] attribute

Version8.3
TypeNew Feature

PHP 8.3 brings a new Attribute named #[\Override] that can be added to added to class methods. When the #[\Override] attribute is added to a class method, PHP enforces that the targeted class method must be overriding or implementing a parent/interface method.

Sub classes and classes that implement a method can make use of this attribute, which prevents accidentally misspelled method names, and removing methods from the parent class or interface.

class Test {
    #[\Override]
    public function myMethod(): void {}
}
Fatal error: Test::myMethod() has #[\Override] attribute, but no matching parent method exists in ... on line ...

In PHP 8.3, the snippet above results in a Fatal error, because PHP enforces the #[\Override] attribute at the compile, and because Test::myMethod is not overriding any parent method, PHP raises a fatal error immediately.

#[\Override] Attribute Class Synopsis

#[Attribute(Attribute::TARGET_METHOD)]
final class Override {
    public function __construct() {}
}
  • \Override attribute is declared in the global namespace.
  • Declared as a final class.

#[\Override] Enforcement

Class methods with the #[\Override] attribute must have a parent method or an interface method. This is consistently available in everywhere a trait/enum/interface/class method has the attribute.

All of the following examples show valid snippets that use the #[\Override] attribute.


Interfaces

interface ParentInterface {
    public function myMethod();
}

interface SubInterface extends ParentInterface {
    #[\Override]
    public function myMethod();
}

Classes

class ParentClass {
    public function myMethod() {}
}

class SubClass extends ParentClass {
    #[\Override]
    public function myMethod() {}
}

Similar to Interfaces, class methods with the #[\Override] method must also be overriding a parent method.

Classes Implementing Interfaces

interface ParentInterface {
    public function myMethod();
}

class MyClass implements ParentInterface {
    #[\Override]
    public function myMethod() {}
}

Enums

Enums cannot extend another Enum, but Enums can still implement interfaces, and the #[\Override] attribute can be applied to Enum methods as well.

interface MyInterface {
    public function myMethod(): void;
}

enum MySubEnum implements MyInterface {
    #[\Override]
    public function myMethod(): void {}
}

Traits

The #[\Override] method is quite useful in traits. Prior to the introduction of #[\Override] attribute, the only way to declare a trait method and make sure it will be overridden by the classes that use that trait is to declare the method as abstract.

With the #[\Override] attribute, it is now possible to enforce that the trait methods will be overridden by the classes that use it.

trait MyTrait {
    #[\Override]
    public function myMethod() {}
}

class MyClass {
    use MyTrait;

    public function myMethod(): void {}
}

In this example, if MyClass does not override the myMethod method, the #[\Override] attribute causes a fatal error:

trait MyTrait {
    #[\Override]
    public function myMethod() {}
}

class MyClass {
    use MyTrait;
}
Fatal error: MyClass::myMethod() has #[\Override] attribute, but no matching parent method exists in ... on line ...

Backward Compatibility Impact

#[\Override] is a new attribute added to PHP 8.3. By design, the existence of the class is not validated at compile time. Adding the #[\Override] attribute to class methods will have no effect in previous PHP versions, but does not cause any syntax or any other errors.

Because the # characters are interpreted as a code comment in PHP, adding any attribute does not cause any syntax errors in PHP 7 or old applications either.

The #[\Override] attribute class can be polyfilled in user-land PHP code. It will not bring the functionality, but any code that inspect attributes of class methods will be able to instantiate an \Override instance.

If any PHP applications declare their own \Override class in the global namespace, this change will cause an error due to the user-land \Override class being a duplicate declaration.


RFC Discussion Implementation