PHP – How to fix the “Warning: preg_replace(): The /e modifier is no longer supported” error in PHP7

PHP - How to disable error log, display errors and error reporting programmatically

Here’s one of the most common issues when upgrading from PHP5.x to PHP7:

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead

Despite being a well-documented issue in PHP manual (deprecated since v5.5 and then unsupported since v7.0.0), the above warning is easily one of the most annoying backward-incompatible changes a developer could face when performing the upgrade: adopting the suggested fix – reimplement the code using the newer and more robust preg_replace_callback function – is not always easy, because the preg_replace usage together with the /e modifier was quite common among PHP-based scripts, apps and interfaces until few years ago.

In the following post we’re sharing three methods we can use to work around the problem: feel free to pick the one that is most suited for your specific scenario.

Fix #1: Stick with the Plan

The first thing we should do is to check if we can effectively use the updated preg_replace_callback function, changing our code accordingly. Needless to say, this is the most proper way to address the issue, simply because it strictly follows the improved PHP 7 approach to regex-based string replacements: ditch the underlying eval (that was the meaning of the /e switch) and use a proper delegate method instead.

Here’s a “old” preg_replace implementation sample, which can be used to turn all lowercase letters into uppercase in a given string:

And here’s the corresponding, PHP7-valid preg_replace_callback version (which also works in PHP5):

As we can see, there are basically three things to do:

  • Use preg_replace_callback instead of preg_replace.
  • Remove the /e modifier to the end of the lookup regex string, keeping all the other ones:    should be replaced with  ,   with  ,   with   and so on (syntax might vary depending of the PHP script).
  • Change the second parameter from a mere string (that will be evaluated into a function) to a more robust callback function returning the replacement string itself: the only real difference between the old string and the one returned by the callback function is the way to insert the matched values: instead of using ugly placeholders such as    ,  ,   (and so on), which we also have to double-escape, we can use the handy    input parameter accepted by our function as an array. The above code shows how we can do that.

Fix #2: Trick the System

There are many scenarios where re-implementing the replacement string into a callback function simply cannot be done: an easy example is the popular PHP-based bulletin board system known as phpBB up to v3.1.x, which uses a template-based approach to handle the BBCODE-to-HTML conversion within their /includes/bbcode.php script. Although they effectively changed the implementation in v3.2.x, there are still tons of forums around the web which proudly uses an outdated version which would be affected by this as soon as PHP gets upgraded to 7.

Here’s the relevant parts of the PHP code (/includes/bbcode.php file, lines 113 and 494 for phpBB 3.1.x but might vary upon different releases):

The second line could be easily upgraded with the method #1 by adding a   statement right after the callback function, in the following way:

However, the first one is not as easy, since the parameter containing the replacement regex(s) is an array filled with template-based rules that might come from various places: filesystem, forum database… It would be quite hard to change them all into functions or to find a way to programmatically transform them.

If you’re facing these kind of scenarios and you desperately need a way out, the “best” thing you can do is to replace the unsupported /e modifier with an actual eval() call in the following way:

We know, this is almost as bad as stealing… and yet it gets the job done, assuming you can use the eval() function (which is disabled by most providers for obvious security reasons).

Fix #3: Dig it under the carpet

If the method #2 was bad, this is even worse. The only reason we’re suggesting this is that we were asked to provide a quick-and-dirty solution for those who cannot perform substantial changes to the script source code and just need to temporarily hide the warning even if they’re unable to fix it.

This fix can also be very useful for those who are upgrading from PHP <= 5.4 to PHP 5.5 – which still supports the /e modifier but outputs a notice about it being deprecated –  without entirely shutting down the E_DEPRECATED and/or E_STRICT level messages. Needless to say, if you plan to use it for PHP 5.5.x, be sure to replace  with   instead in line 2.

If you want to exploit this “carpet-based” strategy even further, for example to prevent PHP from logging some errors to the PHP_errors.log file programmatically, we strongly suggest you to read this post. However, it’s very important to understand that hiding your script errors is almost always the worst thing you can do: be sure to understand all the implications and potential consequences of what you’re doing before proceeding.

Useful references

 

 

 

About Ryan

IT Project Manager, Web Interface Architect and Lead Developer for many high-traffic web sites & services hosted in Italy and Europe. Since 2010 it's also a lead designer for many App and games for Android, iOS and Windows Phone mobile devices for a number of italian companies. Microsoft MVP for Development Technologies since 2018.

View all posts by Ryan

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.