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
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' );
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' );
$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!