PHP RFC: #[\Deprecated] for interfaces
- Version: 0.1
- Date: 2026-05-10
- Author: Daniel Scherzer, daniel.e.scherzer@gmail.com
- Status: Draft
- Implementation: https://github.com/php/php-src/pull/21998
- Discussion thread:
Introduction
The #[\Deprecated] attribute was introduced in PHP 8.4 (deprecated_attribute) and could be used to emit deprecation warnings when calling a function (or class method), or when accessing a class constant (or enum case). Starting in 8.5, deprecation warnings could also be emitted when accessing a global constant (attributes-on-constants) or when useing a trait (deprecated_traits). This RFC proposes to add support for emitting deprecation warnings when an interface is extended or implemented.
<?php #[\Deprecated] trait DemoInterface {} class DemoClass implements DemoInterface {} // Reports: // Deprecated: Interface DemoInterface implemented by DemoClass is deprecated in %s on line %d ?>
Proposal
The #[\Deprecated] attribute will be allowed on interfaces. The existing target validation when applied to classes or enums is maintained.
When the interfaces that a class implements are loaded, any deprecated interfaces emit a deprecation message; these can be converted to an exception via a user error handler, and an uncaught exception will be treated the same as trying to implement a non-interface in terms of registration behavior. The same applies to interfaces extending other interfaces if those other interfaces are marked as deprecated.
Interfaces only emit deprecation warnings when directly extended or implemented, implementing child interfaces or extending implementing classes does not result in extra errors. See the comparison with existing tools below.
Examples
Simple example:
<?php #[\Deprecated] trait DemoInterface {} class DemoClass implements DemoInterface {} // Reports: // Deprecated: Interface DemoInterface implemented by DemoClass is deprecated in %s on line %d ?>
With an exception:
<?php function my_error_handler(int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); } set_error_handler('my_error_handler'); #[\Deprecated] interface DemoInterface {} class DemoClass implements DemoInterface {} // Reports: // Fatal error: Uncaught ErrorException: Interface DemoInterface implemented by DemoClass is deprecated in %s:%d ?>
Tool comparison
Given the following code:
<?php /** * @deprecated */ interface BaseInterface {} interface ChildInterface extends BaseInterface {} class ImplementsBase implements BaseInterface {} class ImplementsBoth implements BaseInterface, ChildInterface {} class ImplementsChild implements ChildInterface {} class ExtendsBaseImplementor extends ImplementsBase {} ?>
existing static analysis tools emit warnings for different sets of declarations. The behavior of the tools and the engine is as follows, where “yes” means a warning is emitted (with the engine behavior coming from using #[\Deprecated] rather than a comment):
| Declaration | Phan | PHPStan | Mago | Psalm | Engine |
|---|---|---|---|---|---|
interface ChildInterface... | yes | yes | yes | no | yes |
class ImlementsBase... | yes | yes | no | yes | yes |
class ImlementsBoth... | yes | yes | no | yes | yes |
class ImlementsChild... | no | no | no | yes | no |
class ExtendsBaseImplementor... | no | no | no | yes | no |
PHPStan is as of the version on the playground (https://phpstan.org/try) on 2026.05.10, Psalm is as of commit 5c1c31c which was on its playground (https://psalm.dev/) on the same date. Phan is as of version 6.0.5, Mago is as of version 1.26.0.
Backward Incompatible Changes
None
Proposed PHP Version(s)
Next PHP (8.6)
RFC Impact
To the Ecosystem
IDEs and static analyzers will likely want to update to surface deprecation messages when an interface is extended or implemented without waiting for PHP to emit the errors.
To Existing Extensions
This lays the engine support for deprecating PHP-provided interfaces, but none are currently marked as deprecated.
To SAPIs
No impact other than deprecations being emitted when a deprecated interface is used.
Open Issues
Make sure there are no open issues when the vote starts!
Future Scope
Other places that #[\Deprecated] could eventually be supported include
- extending a class
- overriding a method
- accessing a property
But the support for deprecating the use of a interface is pretty straightforward and there isn't room for future improvements within the context of deprecating interface.
Voting Choices
Patches and Tests
Implementation
After the RFC is implemented, this section should contain:
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
Rejected Features
Keep this updated with features that were discussed on the mail lists.
Changelog
If there are major changes to the initial proposal, please include a short summary with a date or a link to the mailing list announcement here, as not everyone has access to the wikis' version history.
- v0.1: created