PHP v7.1 and v7.2 Illegal Strings

An update to Yoast SEO v11.1 came out yesterday, causing a few site errors relating to illegal strings in PHP. It made me dust off this post to provide some detail on what that PHP warning is, why it is happening, and how it can be fixed.


Last year I updated all existing client sites that I could to PHP version 7.2, to replace versions 5.6 and 7.0, both of which reached their end of security update lifespans in December of 2018. The current plan for WordPress v5.2 is to drop support for versions of PHP below 5.6, which is targeted to be released on 7 May. If this goes well, the minimum PHP version will be bumped to 7.0 later this year.

We’re only a few weeks away from this change, and a lot of hosts have been informing users that their version will change, or that they should opt-in to update when they can. One issue is that there are some things that work in earlier versions of PHP that will now throw warnings, notices, and errors in newer versions. One of the ones that I had to contend with on a few sites recently was the “Illegal string offset” warning.

Warning: Illegal String Offset

Here’s a few warnings that appeared on a development version of a site that I was upgrading (file path removed for readability):

__Warning:__ Illegal string offset 'menu' in [file location] on line 13
__Warning:__ Illegal string offset 'post_types' in [file location] on line 25
__Warning:__ Illegal string offset 'post_formats' in [file location] on line 36
Code language: PHP (php)

I’m noting that it’s a development environment, because I had WP_DEBUG set to true in my wp-config.php file, which I don’t do on live, production environments. Basically, I ensure that on a live version of a site I don’t have PHP errors/warnings/notices displayed, even if there are some that would otherwise display.

I took a look at that file, which was a configuration file for the theme being used. The relevant lines from that file are below:

/*
 * Theme menu
 */
$theme['menu'] = array(
    THEMENAME,
    'Slideshow',
    'Sidebars',
    'Style',
    'Upload your fonts',
    //'Help'
);

/*
 * Post types
 */
$theme['post_types'] = array(
    'Posts',
    'Pages',
    'Works',
    'Testimonials',
);

/*
 * Post formats
 * aside, gallery, link, image, quote, status, video, audio, chat
 */
$theme['post_formats'] = array( 'gallery' );
Code language: PHP (php)

Can you spot the issue? I didn’t immediately see it myself, as I saw things like $theme['menu'] and thought “how can that be read as a string? The braces clearly indicate that we’re setting an array key.

Explicitly Declaring an Array in PHP

What I didn’t realize was that we were missing something that’s necessary as of PHP v7.1.0: an explicit declaration of the variable $theme as an array. If you take a look at the PHP.net manual entry on PHP Array Syntax Modifying, you’ll see the following note:

Note: As of PHP 7.1.0, applying the empty index operator on a string throws a fatal error. Formerly, the string was silently converted to an array.

So there’s our issue, and with it, a lead on a solution: the theme never explicitly declared the variable $theme to be an array, and so it was assumed to be a string. Since it is no longer being silently converted, we have a warning being thrown.

Fixing the Illegal String Offset Warning

The solution in this case is to add a line to the start of that block of code where we explicitly declare our variable as an array. What that looks like is this:

$theme = array();

/*
 * Theme menu
 */
$theme['menu'] = array(
    THEMENAME,
    'Slideshow',
    'Sidebars',
    'Style',
    'Upload your fonts',
    //'Help'
);
Code language: PHP (php)

By adding $theme = array();, we’re telling PHP, “yes, this is an array, please treat it as such.” It doesn’t have to try to guess what we mean, which newer versions of PHP no longer do anyway.

PHP v7.0+ also introduces strict typing, which is great for being even more explicit in your PHP coding. This makes the code more secure (people can’t put different data types in than you intend), and less liable to break (you will always know what type of data to expect). If you want to learn a bit more, Eric Mann wrote a short introductory post on the topic early last year.

PHP is getting better and better all the time, but this progress sometimes causes old code to break. While this is frustrating, it can also give you the opportunity to review old code with fresh eyes. It’s not always convenient to do this, but it can overall improve your site!


Posted

in

, ,

Comments

5 responses to “PHP v7.1 and v7.2 Illegal Strings”

  1. Kara Franco Avatar

    Thanks for sharing this information, david! Is there any other way to prevent errors and warnings from showing up on a site? My WP_DEBUG is set to false, but I still had error messages showing up on the front end >.<

    1. david Avatar

      There are some settings that could be set differently from your hosting account for PHP error reporting. There are a lot of types of reporting and logging that can be toggled, some of which you can see here: https://www.php.net/manual/en/errorfunc.configuration.php#ini.error-reporting

      In your wp-config.php file you should also be able to hide most with this:

      ini_set(‘display_errors’,’Off’);
      ini_set(‘error_reporting’, E_ALL );
      define(‘WP_DEBUG’, false);
      define(‘WP_DEBUG_DISPLAY’, false);

  2. DΛVID v3.1.3 Avatar

    Follow-up if you’re curious about what an Illegal String Warning is and why you might be getting one on your site with PHP updates.

    twitter.com/davidwolfpaw/s…

  3. What is WP_DEBUG for and how do I use it? – david Wolfpaw Avatar

    PHP normally only displays fatal errors in the browser, or doesn’t load any page content and gives you a “White Screen of Death (WSOD)” if it has a fatal error before the page can load. A fatal error is one in which something is so wrong in the PHP code that it cannot make sense of it to gracefully fail in the background. If I forget to add chocolate chips when making cookies, I still have a perfectly tasty dough. If I forget to add baking soda though, I end up with a flat, gooey mess.

    WordPress has a few features built in to make it easier to see PHP errors while you are testing. You’d want to activate these while developing a new site, theme, or plugin to ensure that you are seeing any PHP errors that come up.

    As mentioned in the last post on PHP Illegal Strings, there are a few failure types in PHP including warnings, notices, and errors. Turning on WP_DEBUG will allow you to see those failure types so that you can fix them in your code.

    Activating WP_DEBUG

    If you have access to all of the files of your WordPress install, you’ll want to edit the wp-config.php file, which is located in the root directory, meaning the same folder that has the wp-admin, wp-content, and wp-includes folders. You’re going to go into that file and add the following line of code near the bottom of the file, but before the stop editing notice:

    define( 'WP_DEBUG', true );

    /* That's all, stop editing! Happy blogging. */

    If that line already exists but says false, change that to true. There can be other lines of code above or below this, but as long as it’s above the comment to stop editing, it’s in the right spot.

    What did we do?

    We’ve now told WordPress that rather than hide PHP errors, we want them to display while viewing the site. WP_DEBUG is a PHP constant, which by convention are written in all caps. We’ve used the PHP define() function to set the value of that constant to a boolean true. Note that we didn’t surround the word true in quotes, otherwise PHP would read it as a string.

    Using WP_DEBUG also allows us to see any deprecated functions that are running on our site. Deprecated functions exist in WordPress but are no longer the standard way to perform a particular tas. As an example, long ago in WordPress history you would get the ID of a category in WordPress with the function the_category_ID(), but now the function to do the same in a better way is get_the_category().

    Using WP_DEBUG_LOG and WP_DEBUG_DISPLAY

    There are some companions to WP_DEBUG that can be used to make it even more helpful. You may not always be able to easily see errors if they are loading behind content, or you may want to keep track of them over time to review later. Two other constants that are built into WordPress that can help are WP_DEBUG_LOG and WP_DEBUG_DISPLAY.

    Using WP_DEBUG_LOG

    Setting up WP_DEBUG_LOG allows you to save all of the debug errors that are getting displayed to a file in your WordPress install. That file gets saved to wp-content/debug.log by default. Whenever an error occurs that WP_DEBUG would display, it will also get saved to that file with a timestamp of when the error occured.

    To turn on WP_DEBUG_LOG you’ll want to define the following constant:

    define('WP_DEBUG_LOG', true);

    You don’t have to worry about creating the debug.log file if it doesn’t already exist. WordPress will do this for you automatically as soon as it has an error to log. So hopefully not right away!

    Changing WP_DEBUG_DISPLAY

    By default, setting WP_DEBUG to true will display all errors on the screen in your browser, on both the visitor-facing frontend, and the admin-facing backend of your site. This is ok while you’re editing a site that isn’t live with other people using it, but you don’t really want those errors displaying to other site visitors. It will make the site look more broken than it is, and can even be a security concern.

    If you want to use WP_DEBUG but don’t want to display errors to the screen, set the following constant:

    define('WP_DEBUG_DISPLAY', false);

    Again, if you don’t set that as false, it will default to true when debug is turned on. If you are setting it to false, you’re probably also setting WP_DEBUG_LOG to true, since otherwise you won’t see the errors on the screen or in a debug log.

    If you want to passively log errors for review later on a live site, just in case any come up, you can combine the three definitions above to turn on debug mode, log errors, and stop them from displaying on the site. I recommend doing this if you don’t have anything else handling these error logs for you, which you’d probably know if you did.

    // Enable WP_DEBUG mode
    define('WP_DEBUG', true);

    // Enable Debug logging to the /wp-content/debug.log file
    define('WP_DEBUG_LOG', true);

    // Disable display of errors and warnings
    define('WP_DEBUG_DISPLAY', false);

    Continuing to Debug Your Site

    The settings above display PHP errors, but they don’t actually do anything to fix them. You’ll need to handle that yourself. Still, they provide an invaluable source of information to determine why something is broken on your site. This won’t show all types of errors that could occur, since not all broken page or feature problems are PHP related.

    What it does do is give you a good footing to begin the fun part of debugging: digging into code and squashing bugs as you find them. In this case the old proverb is true: Knowledge is Power.

    Mentions

  • 💬 What is WP_DEBUG for and how do I use it? – david Wolfpaw
  • 💬 DΛVID v3.1.3

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.