When a class implements an interface, that interface has to exist, or PHP stops with a fatal error. That's a problem for libraries that want to integrate with another library without requiring it. This RFC from Juris Evertovskis proposed letting you put a ? before an interface name: if the interface exists, the class implements it, and if not, PHP skips it. It was declined.

The problem today

Libraries work around this in a few ways. Some wrap the whole class in an if, some define empty stand-in interfaces, and some use class aliases. The RFC points to examples in Symfony, Laravel, WordPress and Carbon.

Here is the if approach, trimmed from the RFC:

if (interface_exists(LaravelExpression::class)) {
    class BaseExpression implements \Stringable, LaravelExpression
    {
        use BaseExpressionImplementation;
    }
} else {
    class BaseExpression implements \Stringable
    {
        use BaseExpressionImplementation;
    }
}

With the RFC, that becomes a single class:

class BaseExpression implements \Stringable, ?LaravelExpression
{
    // The actual implementation
}

How it works

  • The ? applies only to the name right after it, and you can mix required and optional interfaces in any order.
  • It works in an interface's extends list too.
  • PHP checks whether the interface exists when the class is declared, and it still tries the autoloader first.
  • If the interface exists, all the normal rules apply, so your class must still implement every method the interface requires.
  • A class only counts as the types it actually implements. Passing it where a missing interface is expected throws a TypeError.
  • Reflection lists only the interfaces the class actually implements.

What it means for existing code

Nothing breaks. A ? in an interface list isn't valid PHP today, so no working code uses it.

The vote

The vote failed 15 to 19, well short of the two-thirds majority it needed. The poll offered only Yes and No, and voting closed on March 29, 2025.