#[Deprecated] Attribute

php.internals

Benjamin Eberlei

5 years ago
Hi internals, I have updated the RFC for a #[Deprecated] attribute that wasn't completed for PHP 8.0 due to time constraints and I am able to restart the discussion now. https://wiki.php.net/rfc/deprecated_attribute The following updates have been made: - focus on only method and function deprecations for now, removed class/property/constant deprecations. - a section on explaining the runtime effects of deprecations in PHP, and a note that this RFC is about completing deprecation support within the existing model, while changes to deprecations in general are out of scope / a disjunct concern for a different RFC. Sara proposed a much improved implementation over my initial patch, by using the already existing ZEND_ACC_DEPRECATED constant on userland functions. The resulting implementation is therefore much simpler and really just extending existing function deprecation support from internal to userland functions. You can find the PR here: https://github.com/php/php-src/pull/6521 Let me know what you think. greetings Benjamin

Nicolas Grekas

5 years ago
Hi Benjamin, I have updated the RFC for a #[Deprecated] attribute that wasn't completed
> for PHP 8.0 due to time constraints and I am able to restart the discussion > now. > > https://wiki.php.net/rfc/deprecated_attribute > > The following updates have been made: > > - focus on only method and function deprecations for now, removed > class/property/constant deprecations. > - a section on explaining the runtime effects of deprecations in PHP, and a > note that this RFC is about completing deprecation support within the > existing model, while changes to deprecations in general are out of scope / > a disjunct concern for a different RFC. > > Sara proposed a much improved implementation over my initial patch, by > using the already existing ZEND_ACC_DEPRECATED constant on userland > functions. The resulting implementation is therefore much simpler and > really just extending existing function deprecation support from internal > to userland functions. You can find the PR here: > > https://github.com/php/php-src/pull/6521 >
Thanks for the RFC. It would be great to allow adding this attribute on classes. What about allowing it right now and not bind it to any runtime side-effect? That would allow static analyzers to do their job. Same for consts and properties by the way. Also, it would be very useful to add named parameters to the attribute, namely: "package" (the name of the package that declares the deprecation) and "version" (the version of that package that introduced the deprecation), next to the message. This is critical info when building reports of deprecations. Thanks for considering, Nicolas

Sara Golemon

5 years ago
On Tue, Dec 22, 2020 at 12:35 PM Nicolas Grekas < nicolas.grekas+php@gmail.com> wrote:
> It would be great to allow adding this attribute on classes. What about > allowing it right now and not bind it to any runtime side-effect? That > would allow static analyzers to do their job. Same for consts and > properties by the way. > > Also, it would be very useful to add named parameters to the attribute, > namely: "package" (the name of the package that declares the deprecation) > and "version" (the version of that package that introduced the > deprecation), next to the message. > > This is critical info when building reports of deprecations. > >
You could do that now with a polyfill from userspace. If the annotation need not have an effect, then it's just any other userspace implementation. -Sara

Weirdan

5 years ago
On Tue, Dec 22, 2020 at 8:55 PM Sara Golemon <pollita@php.net> wrote:
> > You could do that now with a polyfill from userspace. If the annotation > need not have an effect, then it's just any other userspace implementation. >
It's possible now, while the attribute is not provided by PHP. But once it gets introduced and *if* it forbids usage on some elements it wouldn't be possible to fix this from userspace.
-- Best regards, Bruce Weirdan mailto: weirdan@gmail.com

Brent

5 years ago
Hi Sara
> On 22 Dec 2020, at 19:54, Sara Golemon <pollita@php.net> wrote: > > On Tue, Dec 22, 2020 at 12:35 PM Nicolas Grekas < > nicolas.grekas+php@gmail.com> wrote: > >> It would be great to allow adding this attribute on classes. What about >> allowing it right now and not bind it to any runtime side-effect? That >> would allow static analyzers to do their job. Same for consts and >> properties by the way. >> >> Also, it would be very useful to add named parameters to the attribute, >> namely: "package" (the name of the package that declares the deprecation) >> and "version" (the version of that package that introduced the >> deprecation), next to the message. >> >> This is critical info when building reports of deprecations. >> >> > You could do that now with a polyfill from userspace. If the annotation > need not have an effect, then it's just any other userspace implementation.
The difference is that PHP core has the ability to force standarization. There's already JetBrains' implementation of #[Deprecated], which Psalm and PhpStan also support, but it's not a real standard. Maybe the FIG would one day step in to decide these kinds of things, but the reality is that many major frameworks don't follow FIG as closely as they used to. I think there's value in adding attributes in the core, with the goal only being static analysis. It'll allow for consistency and that's a valuable thing.
> > -Sara
Kind regards Brent

Benjamin Eberlei

5 years ago
On Wed, Jan 13, 2021 at 1:05 PM Brent Roose <brendt@stitcher.io> wrote:
> Hi Sara > > > On 22 Dec 2020, at 19:54, Sara Golemon <pollita@php.net> wrote: > > > > On Tue, Dec 22, 2020 at 12:35 PM Nicolas Grekas < > > nicolas.grekas+php@gmail.com> wrote: > > > >> It would be great to allow adding this attribute on classes. What about > >> allowing it right now and not bind it to any runtime side-effect? That > >> would allow static analyzers to do their job. Same for consts and > >> properties by the way. > >> > >> Also, it would be very useful to add named parameters to the attribute, > >> namely: "package" (the name of the package that declares the > deprecation) > >> and "version" (the version of that package that introduced the > >> deprecation), next to the message. > >> > >> This is critical info when building reports of deprecations. > >> > >> > > You could do that now with a polyfill from userspace. If the annotation > > need not have an effect, then it's just any other userspace > implementation. > > The difference is that PHP core has the ability to force standarization. > There's already JetBrains' implementation of #[Deprecated], which Psalm and > PhpStan also support, but it's not a real standard. Maybe the FIG would one > day step in to decide these kinds of things, but the reality is that many > major frameworks don't follow FIG as closely as they used to. I think > there's value in adding attributes in the core, with the goal only being > static analysis. It'll allow for consistency and that's a valuable thing. >
I want to keep #[Deprecated] on other elements than functions / methods out of this RFC, because they require entirely different implementation approaches. We identified in the PR already that this should at some point be standardized in core, because internal attributes will currently not be able to support extension through inheritance by userland for implementation reasons. My next RFC update will reflect this future scope.

Ben Ramsey

1 year ago
> On Jan 13, 2021, at 06:43, Benjamin Eberlei <kontakt@beberlei.de> wrote: > > On Wed, Jan 13, 2021 at 1:05 PM Brent Roose <brendt@stitcher.io> wrote: > >> Hi Sara >> >>> On 22 Dec 2020, at 19:54, Sara Golemon <pollita@php.net> wrote: >>> >>> On Tue, Dec 22, 2020 at 12:35 PM Nicolas Grekas < >>> nicolas.grekas+php@gmail.com> wrote: >>> >>>> It would be great to allow adding this attribute on classes. What about >>>> allowing it right now and not bind it to any runtime side-effect? That >>>> would allow static analyzers to do their job. Same for consts and >>>> properties by the way. >>>> >>>> Also, it would be very useful to add named parameters to the attribute, >>>> namely: "package" (the name of the package that declares the deprecation) >>>> and "version" (the version of that package that introduced the >>>> deprecation), next to the message. >>>> >>>> This is critical info when building reports of deprecations. >>>> >>>> >>> You could do that now with a polyfill from userspace. If the annotation >>> need not have an effect, then it's just any other userspace implementation. >> >> The difference is that PHP core has the ability to force standarization. >> There's already JetBrains' implementation of #[Deprecated], which Psalm and >> PhpStan also support, but it's not a real standard. Maybe the FIG would one >> day step in to decide these kinds of things, but the reality is that many >> major frameworks don't follow FIG as closely as they used to. I think >> there's value in adding attributes in the core, with the goal only being >> static analysis. It'll allow for consistency and that's a valuable thing. >> > > I want to keep #[Deprecated] on other elements than functions / methods out > of this RFC, because they require entirely different implementation > approaches. > > We identified in the PR already that this should at some point be > standardized in core, because internal attributes will currently not be > able to support extension through inheritance by userland for > implementation reasons. > > My next RFC update will reflect this future scope.
Last night, I identified a need for `#[Deprecated]` on a userland class in one of my libraries, but I had to settle on `@deprecated` for the widest range of compatibility. Has there been anymore thought on putting together an implementation for this? I’m happy to draft an RFC if someone is able to help with the implementation. I don’t understand the complexities around the implementation, but is this something that could make it into 8.5, provided an RFC vote passes? Cheers, Ben

Daniel Scherzer

1 year ago
On Tue, May 27, 2025 at 9:41 PM Ben Ramsey <ramsey@php.net> wrote:
> > Last night, I identified a need for `#[Deprecated]` on a userland class in > one of my libraries, but I had to settle on `@deprecated` for the widest > range of compatibility. > > Has there been anymore thought on putting together an implementation for > this? I’m happy to draft an RFC if someone is able to help with the > implementation. I don’t understand the complexities around the > implementation, but is this something that could make it into 8.5, provided > an RFC vote passes? > > Cheers, > Ben > >
I'd be willing to work on the implementation, but what I'm wondering is what exactly it would mean to deprecate a class. Without a clear idea of the goal, I didn't include this in https://news-web.php.net/php.internals/127305 even though I had considered it. Would a deprecated class * Emit warnings when constructed? Just deprecate the constructor, https://3v4l.org/DNrqm * Emit warnings when used as a type? But we allow types to include classes that don't exist (https://3v4l.org/pdkbv) so needing to look up the types that are declared to emit warnings (rather than just when used to verify that the type is respected) would presumably have a performance impact. * Emit warnings when extended? I suggested that in my email a few weeks ago, and when I have time I was going to look into that - I was thinking something like `#[\WillBeFinal]` that would work for classes, methods, properties, and constants, and would emit warnings just like `#[\Deprecated]` but not when a method is called or a constant is used, just when things are overridden What were you thinking in terms of desired semantics? --Daniel

Benjamin Eberlei

1 year ago
Am 28.05.2025, 06:54:22 schrieb Daniel Scherzer <daniel.e.scherzer@gmail.com
>:
> On Tue, May 27, 2025 at 9:41 PM Ben Ramsey <ramsey@php.net> wrote: > >> >> Last night, I identified a need for `#[Deprecated]` on a userland class >> in one of my libraries, but I had to settle on `@deprecated` for the widest >> range of compatibility. >> >> Has there been anymore thought on putting together an implementation for >> this? I’m happy to draft an RFC if someone is able to help with the >> implementation. I don’t understand the complexities around the >> implementation, but is this something that could make it into 8.5, provided >> an RFC vote passes? >> >> Cheers, >> Ben >> >> > > I'd be willing to work on the implementation, but what I'm wondering is > what exactly it would mean to deprecate a class. Without a clear idea of > the goal, I didn't include this in > https://news-web.php.net/php.internals/127305 even though I had > considered it. Would a deprecated class > > * Emit warnings when constructed? Just deprecate the constructor, > https://3v4l.org/DNrqm > * Emit warnings when used as a type? But we allow types to include classes > that don't exist (https://3v4l.org/pdkbv) so needing to look up the types > that are declared to emit warnings (rather than just when used to verify > that the type is respected) would presumably have a performance impact. > * Emit warnings when extended? I suggested that in my email a few weeks > ago, and when I have time I was going to look into that - I was thinking > something like `#[\WillBeFinal]` that would work for classes, methods, > properties, and constants, and would emit warnings just like > `#[\Deprecated]` but not when a method is called or a constant is used, > just when things are overridden > > What were you thinking in terms of desired semantics? > > —Daniel >
Hi Daniel, Hi Ben, Tim and I ideated on this topic before, but we haven’t gotten further yet. I wanted to share my notes though, so that you have them as one idea. Its not more than a brain dump though: - Deprecated classes - mark the following elements deprecated: - constructor method (what if it doesnt have one?) - public static methods - public static properties - public constants - not public properties or methods, because the message is already generated on new DeprecatedClass - during generating the message see if its classed based and slightly change message to indicate its a class based deprecation

tag Knife

1 year ago
On Tue, 27 May 2025 at 20:05, Ben Ramsey <ramsey@php.net> wrote:
> > On Jan 13, 2021, at 06:43, Benjamin Eberlei <kontakt@beberlei.de> wrote: > > > > On Wed, Jan 13, 2021 at 1:05 PM Brent Roose <brendt@stitcher.io> wrote: > > > >> Hi Sara > >> > >>> On 22 Dec 2020, at 19:54, Sara Golemon <pollita@php.net> wrote: > >>> > >>> On Tue, Dec 22, 2020 at 12:35 PM Nicolas Grekas < > >>> nicolas.grekas+php@gmail.com> wrote: > >>> > >>>> It would be great to allow adding this attribute on classes. What > about > >>>> allowing it right now and not bind it to any runtime side-effect? That > >>>> would allow static analyzers to do their job. Same for consts and > >>>> properties by the way. > >>>> > >>>> Also, it would be very useful to add named parameters to the > attribute, > >>>> namely: "package" (the name of the package that declares the > deprecation) > >>>> and "version" (the version of that package that introduced the > >>>> deprecation), next to the message. > >>>> > >>>> This is critical info when building reports of deprecations. > >>>> > >>>> > >>> You could do that now with a polyfill from userspace. If the annotation > >>> need not have an effect, then it's just any other userspace > implementation. > >> > >> The difference is that PHP core has the ability to force standarization. > >> There's already JetBrains' implementation of #[Deprecated], which Psalm > and > >> PhpStan also support, but it's not a real standard. Maybe the FIG would > one > >> day step in to decide these kinds of things, but the reality is that > many > >> major frameworks don't follow FIG as closely as they used to. I think > >> there's value in adding attributes in the core, with the goal only being > >> static analysis. It'll allow for consistency and that's a valuable > thing. > >> > > > > I want to keep #[Deprecated] on other elements than functions / methods > out > > of this RFC, because they require entirely different implementation > > approaches. > > > > We identified in the PR already that this should at some point be > > standardized in core, because internal attributes will currently not be > > able to support extension through inheritance by userland for > > implementation reasons. > > > > My next RFC update will reflect this future scope. > > > Last night, I identified a need for `#[Deprecated]` on a userland class in > one of my libraries, but I had to settle on `@deprecated` for the widest > range of compatibility. > > Has there been anymore thought on putting together an implementation for > this? I’m happy to draft an RFC if someone is able to help with the > implementation. I don’t understand the complexities around the > implementation, but is this something that could make it into 8.5, provided > an RFC vote passes? > > Cheers, > Ben > >
I have needed this as well at work for a shared library and i'm sure many library authors would use it too. Current IDE's like jetbrains has support for #[Deprecated($reason, $replacement)] which will throw warning in the IDE, see their implementation here: https://github.com/JetBrains/phpstorm-attributes?tab=readme-ov-file#deprecated If this could be supported at a language level, package authors, frameworks and internal company libraries would benefit from it. I see no reason why anyone would be against the idea, other than pure chaos evil.

Ben Ramsey

1 year ago
On 6/1/25 17:31, fennic log wrote:
> I have needed this as well at work for a shared library and i'm sure many > library authors would use it too. > Current IDE's like jetbrains has support for #[Deprecated($reason, > $replacement)] which will throw warning in the IDE, > see their implementation here: > https://github.com/JetBrains/phpstorm-attributes?tab=readme-ov-file#deprecated > > If this could be supported at a language level, package authors, frameworks > and internal company libraries would benefit from it. > I see no reason why anyone would be against the idea, other than pure chaos > evil. >
I don't think the issue is that anyone is against the idea. I think the issue is that it's unclear what the behavior should be. Following from Benjamin Außenhofer's post:
> - Deprecated classes > - mark the following elements deprecated: > - constructor method (what if it doesnt have one?) > - public static methods > - public static properties > - public constants > - not public properties or methods, because the message is already > generated on new DeprecatedClass > - during generating the message see if its classed based and > slightly change message to indicate its a class based deprecation
I hadn't gotten very far along in thinking about it. What led me to resurrect this old thread was this: I wanted to mark a class a deprecated because I'll be removing it in the next major version of ramsey/uuid. When anyone tries to "use" the class, I'd like them to see a deprecation message. "Use" is doing a lot of heavy-lifting here. When I annotate the class with `@deprecated`, that helps in several ways: * JetBrains IDEs show the class name with a strike-through line * PHPStan and Psalm complain about its use * PHP_CodeSniffer can be configured to complain about it * Other tooling I might not be aware of does stuff The goal is to make sure users are aware of the deprecation. If we don't change to the language to support `#[\Deprecated]` at the class level, what is the common practice library authors should follow that will allow all the tooling (and PHP's deprecation messages) to make users aware? * Add the attribute to the constructor? * Add it to all public static properties, methods, constants? If all the tooling will appropriately warn the user when the attribute is on the constructor, then I don't think there's a need to make a change to the language. I guess I'll need to do a little investigation now to see how all the tools respond when using the attribute on various elements. Cheers, Ben

Girgias

5 years ago
On Sat, 19 Dec 2020 at 10:19, Benjamin Eberlei <kontakt@beberlei.de> wrote:
> Hi internals, > > I have updated the RFC for a #[Deprecated] attribute that wasn't completed > for PHP 8.0 due to time constraints and I am able to restart the discussion > now. > > https://wiki.php.net/rfc/deprecated_attribute > > The following updates have been made: > > - focus on only method and function deprecations for now, removed > class/property/constant deprecations. > - a section on explaining the runtime effects of deprecations in PHP, and a > note that this RFC is about completing deprecation support within the > existing model, while changes to deprecations in general are out of scope / > a disjunct concern for a different RFC. > > Sara proposed a much improved implementation over my initial patch, by > using the already existing ZEND_ACC_DEPRECATED constant on userland > functions. The resulting implementation is therefore much simpler and > really just extending existing function deprecation support from internal > to userland functions. You can find the PR here: > > https://github.com/php/php-src/pull/6521 > > Let me know what you think. > > greetings > Benjamin >
Just to clarify this raises an E_DEPRECATED right? Could it make sense to raise E_USER_DEPRECATED instead? Best regards, George P. Banyard

Marco Pivetta

5 years ago
On Sun, Jan 10, 2021 at 2:48 AM G. P. B. <george.banyard@gmail.com> wrote:
> Just to clarify this raises an E_DEPRECATED right? > Could it make sense to raise E_USER_DEPRECATED instead? >
I hadn't checked this before, but as per George's message, this is worrying. I've been quite loud about it in the past, but static metadata definitions should really not lead to runtime side-effects, especially if not pure (error handling system tripped here). I'd be totally for a built-in `#[Deprecated]` attribute if it did **NOT** have a runtime behavior, which is an absolute no-go from my PoV. This stuff is easily introspectible via tools like phpstan, psalm, phan, and does not need to lead to more problematic runtime issues. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Benjamin Eberlei

5 years ago
On Wed, Jan 13, 2021 at 1:34 PM Marco Pivetta <ocramius@gmail.com> wrote:
> On Sun, Jan 10, 2021 at 2:48 AM G. P. B. <george.banyard@gmail.com> wrote: > >> Just to clarify this raises an E_DEPRECATED right? >> Could it make sense to raise E_USER_DEPRECATED instead? >> > > I hadn't checked this before, but as per George's message, this is > worrying. > > I've been quite loud about it in the past, but static metadata definitions > should really not lead to runtime side-effects, especially if not pure > (error handling system tripped here). > > I'd be totally for a built-in `#[Deprecated]` attribute if it did **NOT** > have a runtime behavior, which is an absolute no-go from my PoV. > > This stuff is easily introspectible via tools like phpstan, psalm, phan, > and does not need to lead to more problematic runtime issues. >
I get where you are coming from, but side-effect based notices/deprecations is just the way PHP works at the moment and as such this existing mechanism should be used and extended. I do have (vague) plans to tackle alternative ways to process notices/deprecations in the future, but this is independent from that and #[Deprecated] would automatically tie into a change of this kind.

Marco Pivetta

5 years ago
Hey Benjamin On Wed, Jan 13, 2021 at 1:47 PM Benjamin Eberlei <kontakt@beberlei.de> wrote:
> I get where you are coming from, but side-effect based > notices/deprecations is just the way PHP works at the moment and as such > this existing mechanism should be used and extended. > > I do have (vague) plans to tackle alternative ways to process > notices/deprecations in the future, but this is independent from that and > #[Deprecated] would automatically tie into a change of this kind. >
If you have vague plans, perhaps introducing `#[Deprecated]` first, then proposing a separate RFC for the runtime behavior? For me, runtime behavior is: * a big problem with existing tools that started doing this * a production outage risk * something that attributes shouldn't do anyway, at least not out of the box (AOP OOTB is quite ugly and unexpected) As usual, I'm fighting for pushing things into compile-time rather than runtime, as runtime in PHP is already quite the nightmare of things to keep in mind. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Rowan Collins

5 years ago
On 13/01/2021 12:51, Marco Pivetta wrote:
> For me, runtime behavior is: > > [...] > * a production outage risk
If your production code can cause outages based on E_DEPRECATED notices, then that's a bug in your code. I can't think of any justification for a production system to abort because of a notification about future changes. If we have to consider every introduction of a deprecation notice as a breaking change, then we're stuck in a Catch-22, because the whole point of such notices is to warn of upcoming breaking changes.
> As usual, I'm fighting for pushing things into compile-time rather than > runtime
In principle, I do agree with this, but as Benjamin says, it's quite a meaty topic in its own right. It's also unlikely to ever eliminate 100% of runtime checks, because you can't statically analyse completely dynamic code. Defining #[Deprecated] as "do what all the other deprecations do", and later changing that *for all existing deprecations* seems reasonable. Regards,
-- Rowan Tommins [IMSoP]