- Dealing with deprecations
- # 1. Deprecations are helpful
- # 2. Deprecations can be silenced
- # 3. They are notices, not fatal errors
- # 4. Automation
- Prevent E_DEPRECATED error messages in PHP
- In PHP.ini
- In code with error_reporting
- Making it safe for earlier versions of PHP
- Development vs production
- Check Out These Related posts:
- Disabling PHP Deprecation Warnings and Notices
- 2 Answers 2
Dealing with deprecations
You’ve probably dealt with them at one point your programming career:
Deprecated: Creation of dynamic property Post::$name is deprecated in /in/4IreV on line 10
Despite them being annoying and frustrating to many developers, they actually serve a purpose. I would even say you will appreciate them once you understand their goal, and how to deal with them. Let’s take a look!
Oh, by the way: you can watch this blog post as a vlog if you prefer that:
# 1. Deprecations are helpful
It’s a common complaint: «why do my PHP scripts break with minor version updates??». And quite right: PHP has a tendency to add deprecation notices in minor releases, which tend to be audibly present when upgrading a project. Take for example PHP 8.1, where suddenly logs were filled with these kinds of warnings:
Return type should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[ReturnTypeWillChange] attribute should be used to temporarily suppress the notice
It’s important to understand what deprecations are about: they aren’t errors, they are notices. They are a way of notifying PHP developers about a breaking change in the future. They want to warn you up front, to give you plenty of time to deal with that upcoming breaking change.
Of course, one could ask: are these breaking changes and fancy features really necessary? Do we really need to change internal return types like IteratorAggregate :: getIterator (): Traversable , do we really need to disallow dynamic properties?
In my opinion — and it’s shared by the majority of PHP internal developers — yes. We need to keep improving PHP, it needs to grow up further. And that sometimes means introducing a breaking change, like for example when internals add return types to built-in class methods: if you’re extending IteratorAggregate in userland code, you will need to make some changes. The language needs to evolve.
Overall I’d say that, despite some of the annoyances that come with such an evolving language, it’s for the better.
And luckily we have a mechanic like deprecation notices: they tell us that something will break in the future, but that we can still use it today. We can incrementally make changes and updates around our codebase.
# 2. Deprecations can be silenced
Second, PHP internals go to great lengths to help userland developers in dealing with deprecations. Thanks to the addition of attributes in PHP 8.0, we now have a much better and standardized way of communication between our code and PHP’s interpreter.
For example: you can tag userland code with the ReturnTypeWillChange attribute in order to prevent deprecation notices being shown.
final class MyIterator implements \IteratorAggregate < #[\ReturnTypeWillChange] public function getIterator() < // … > >
Of course, this code will break in PHP 9.0, so while silencing deprecation notices is a short-term solution; you will need to fix them if you ever want to upgrade to the next major version:
final class MyIterator implements \IteratorAggregate < public function getIterator(): \Traversable < >>
One more example maybe? With dynamic properties being deprecated in PHP 8.2, you can mark classes with the AllowDynamicProperties attribute, making it so that they allow dynamic properties again and suppress the deprecation notice:
#[\AllowDynamicProperties] class Post < >// … $post->title = 'Name';
# 3. They are notices, not fatal errors
PHP code will keep working just fine, even when parts of it trigger deprecation notices. Of course, you know by now that it’s in your best interest to fix them if you ever want to upgrade to the next major version, but you don’t need to do it right now. It’s perfectly ok to upgrade your production projects and deal with deprecations notices over time.
I’d even recommend disabling deprecation notices on production altogether, or at least not show them to your end users:
error_reporting(E_ALL ^ E_DEPRECATED);
Maybe you can keep track of them using an external error tracker for the first months, to get a clear image of the places you’ll need to fix those deprecations. But above all: deprecation notices shouldn’t be blockers when upgrading to the latest minor PHP version.
# 4. Automation
Lastly, keep in mind that you don’t need to do the boring tasks by hand. There are tools like Rector and phpcs that can take care of many upgrading issues for you. Usually it’s a matter of running a script that takes a couple of minutes at most to scan and fix your codebase. That’s work that you might need days for if you’d do it by hand.
It’s not difficult or time consuming anymore to deal with PHP upgrades. In fact, deprecations help tremendously to create a smoother upgrade path and prepare your codebase for the future.
I like deprecations, you should too.
Prevent E_DEPRECATED error messages in PHP
PHP 5.3 introduced a new error reporting level E_DEPRECATED which is triggered when deprecated functions and methods are used, such as the old style ereg() regular expression functions. This post shows how to suppress E_DEPRECATED error messages.
In PHP.ini
To show all errors other than E_DEPRECATED in the php.ini file, adjust the error_reporting setting as shown below. Note this should only be done for installs of PHP 5.3+.
error_reporting = E_ALL & ~E_DEPRECATED
To suppress notices as well:
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
In code with error_reporting
You can either straight out set the error reporting level like so:
error_reporting(E_ALL &~ E_DEPRECATED); error_reporting(E_ALL &~ E_NOTICE &~ E_DEPRECATED);
or remove E_DEPRECATED from the current error_reporting level:
error_reporting(error_reporting() & ~E_DEPRECATED);
Making it safe for earlier versions of PHP
The only catch with the above error_reporting examples is that if you’re running the same code on e.g. PHP 5.2 as well as PHP 5.3 then you’ll get a notice in PHP 5.2 (and earlier) like «Notice: Use of undefined constant E_DEPRECATED».
To avoid triggering this notice check if E_DEPRECATED is defined:
Development vs production
While you certainly won’t want to trigger E_DEPRECATED messages in production, you may well want to show them in development to make it easy to locate and update code with deprecated functions. (Note you can suppress the display of error messages regardless of the error_reporting level with display_errors).
In my case, I’ve been using SilverStripe 2.4 which occasionally makes use of the ereg() functions and I prefer not to have the messages displayed even in development. SS 3 will come out later this year and I’m sure they’ll have replaced the ereg functions with preg equivilents. Maybe then I’ll switch back E_DEPRECATED in development.
Check Out These Related posts:
Disabling PHP Deprecation Warnings and Notices
I’ve been using and configuring PHP, but now I’m stuck in a weird problem, so I am going to ask you guys for help. I don’t want to see Deprecation Warnings and Notices in a production server, however I would like to see other error messages, such as Syntax Errors for example. I’m running PHP 5.3.3-1ubuntu9.3 with Suhosin-Patch on Ubuntu 10.10 In my /etc/php5/apache2/php.ini I’ve the following line:
error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE
I’ve restarted the webserver. In the virtual host configuration there is no php_admin_value messing with this configuration, in the folder there isn’t any .htaccess file. Nevertheless Deprecation Warnings and Notices are still shown.
2 Answers 2
First of all I want to thank binfalse for answering this question, however my problem was not solved with his suggestion and notices continued to show.
This is because PHP has several places where configuration can be set. While I had an idea of the precedence of those settings, I decided to test them experimentally to be sure of what I am going to say in this answer.
So here is a list of those places, from the more global to the more specific. Each setting lower in the list can override a setting that come before.
- The php.ini configuration file. In case of Ubuntu there are two of them, /etc/php5/apache2/php.ini is the one used for php apache module. It will have a global effect on all virtual hosts.
- The conf.d directory. Actually not all installations will have this modularized configuration, but in case of Ubuntu is located in /etc/php5/apache2/conf.d for the apache module. Any file added in this directory is going to be added to main php.ini configuration with higher precedence than php.ini. In other words any setting here will override settings in php.ini — I tested adding an error.ini. It will have a global effect on all vitual hosts.
- Apache virtual host configuration. Generally set in /etc/apache2/sites-available, every virtual host can have different settings. Inside the VirtualHost tag it’s possible to include «php_value error_reporting «, where value is the numeric result of the boolean operations on the constants. In this configuration, in fact is not allowed to use the mnemonic constants but only a numeric value. It will affect only a single virtual host. It will override above settings.
- .htaccess. It’s also possible to set configuration values and in particular the error_reporting setting also in .htaccess, with the same syntax described in 3. It will affect only the directory in which .htaccess is located and all subdirectories. It will override above settings, in this case is not necessary to restart apache.
- Source code. The last place where this setting can be altered is directly in the executed PHP source. If used, will override all previous settings, and that’s exactly what I was facing. It can be set calling the function «error_reporting()» or with «ini_set(«error_reporting», )». Compile errors could still show, because the script won’t be executed in that case.