PHP's implements
keyword allows classes to declare that they implement one or more interfaces. This mechanism is strict: the specified interfaces must exist at runtime. While this strictness is usually beneficial, it can create challenges when developing libraries that need to interoperate with other optional libraries or different versions of libraries and when creating projects that need to be compatible with multiple PHP versions and usable with or without some PHP extensions.
In such scenarios developers resort to workarounds like
These solutions introduce complexity and a maintenance burden. The conditional declarations may sometimes confuse IDEs and static analysis tools that pick up the multiple definitions. If an optional interface is mocked by a dummy, the implementing class contains no indication of that and misleads the reader into thinking that an actual interface with that name is defined in a meaningful way.
By prefixing an interface name with ?
, a class can optionally implement an interface. If the interface exists, the class will implement it; otherwise, the declaration will be ignored without causing an error.
This allows the developer to clearly announce that the class is interoperable with an interface, but does not require the interface per se.
namespace MyNamespace; use ExternalNamespace\TheInterface; class MyClass implements ?TheInterface { // ... }
If \ExternalNamespace\TheInterface
exists, MyClass
will implement it. It will behave as if the class was declared as class MyClass implements TheInterface
.
If it doesn't exist, MyClass
will work as if it was declared without implements ?TheInterface
.
Optional interfaces can appear on an interface list together with required interfaces in any order. The ?
applies only to the name directly following the token.
class MyClass1 implements A, B, ?C, ?D {} class MyClass2 implements ?C, ?D, A, B {} class MyClass3 implements A, ?C, ?D, B {} class MyClass4 implements ?C, A, B, ?D {}
All of these classes implement and require interfaces A
and B
while the interfaces C
and D
will only be implemented if they exist.
An interface can also be optional when it's in an extends
list of another interface. The list of extandable interface names works just like the implements
list for classes.
interface MyInterface extends RequiredInterface, ?OptionalInterface {}
None.
Classes that do not use the ?
token in the interface list will function as before. Before this RFC the ?
token in interface lists is not valid, therefore a runnable code that would be affected does not exist.
Next PHP 8.x.
It is necessary to develop RFC's with opcache in mind, since opcache is a core extension distributed with PHP.
Please explain how you have verified your RFC's compatibility with opcache.
I have not verified the compatibility with the opcache yet.
Currently this RFC does not add the optionality information in the Reflection API.
Include these so readers know where you are heading and can discuss the proposed voting options.
After the project is implemented, this section should contain
Keep this updated with features that were discussed on the mail lists.