Last week I updated three large WordPress sites for Praxis from PHP 5.6 to 7.2. Here is the process I used on all three to make it a smooth transition.
Note: I do contract work and can help you figure this upgrade out. Reach out if you are interested in getting a quote.
1. Figure out the scope of the problem.
First you need to know how much time you should plan to spend doing this work. A quick way to find the scope of the problem is to run the PHP Compatibility Checker plugin. It checks your themes and plugins, spitting out errors, warnings, and filenames/line numbers of the offending code so you know where to start.
- Small theme upgrades?
- Plugin updates?
- Massive refactoring of custom code?
Even if you get a 100% clean pass with the compatibility checker, I suggest going through the rest of my list. The compatibility checker isn’t perfect. You don’t want to roll those downtime dice. Fool me one time, and all that.
2. Test the upgrade locally.
Copy down your current theme and database into your local development environment. This is important. Don’t use the version you have from work you did a few months ago. Stuff changes on the server all the time. Pull down a copy to be safe. Configure your local environment to use PHP 7.2. If you are unsure whether or not you are on 7.2 locally, you can always use a WordPress plugin like Debug Info to check. Also make sure to turn on error reporting in your
Don’t have a local development environment yet? I like Valet.
While you are at it, I suggest upgrading your WordPress core to the latest version (5.1.1 as of this writing) and updating all of your plugins. Rip that bandaid off. On the plus side, it will probably make the PHP upgrade process easier, too.
3. Find, diagnose, and solve any issues.
This is either the easiest or hardest step. If your site looks fine and everything functions as it should, great! You won the lottery.
It is probably worth double checking that you actually are on PHP 7.2 with the debug plugin mentioned above. Also worth clicking all around your site and checking everything. Sometimes most of the site will load, but you’ll get weird inline error messages like this:
Warning: Use of undefined constant Y - assumed ‘Y’ (this will throw an Error in a future version of PHP) in /nas/content/staging/creativecourse/wp-content/themes/business-pro-theme/page-archive.php on line 70
If you navigate to the site locally and all you see is a sea of errors like I did on one site, you have some work cut out for you. Here are some tips:
- If the errors include
wp-admin in the file paths, you need to update your WordPress core.
- If the errors include
wp-content/themes/ in the file path, and you don’t have any custom work done on the site, the quickest fix is to upgrade your theme or find a new one.
- If the errors include
wp-content/plugins/somepluginname/ in the file path, find that plugin and disable it or update it and try again. You should still be able to get to your
/wp-admin/ dashboard even with a broken site because the most recent core works with PHP 7.2.
- If your site includes a bunch of custom code and the errors are happening with the custom code, you have more work to do. If you are comfortable debugging and fixing it, great! If not, you might need to call the person or company who wrote it. Or decide if you can do without it. Hopefully you followed conventions and put it in a child theme.
Keep track of the changes you make. I keep a running list in my favorite notes app. Theme updates, core updates, plugin updates, and code changes. Write it all down. Better yet, version control it with git and commit along the way.
If you have any premium plugins that require activation keys, make sure that you contact the developer to get two extra development keys for local testing and production. Most will provide those to you at no extra cost. Some platforms give you 5 keys per purchase anyway just for this reason. I decided to roll the dice and not get keys for one plugin, and ended up crashing my production site with the upgrade because I didn’t test that plugin. Don’t be like me.
All three of my sites needed some work done, even the newest of the three. One didn’t load at all until I made some theme updates. One plugin crashed a site and had no updates available, so I had to do without. Some custom code I had written needed updates, too. It took me a few afternoons to sort it all out.
4. Deploy to a staging environment on PHP 7.2 first.
Once you have everything sorted out locally and you’ve triple tested everything, go ahead and push your work up to a staging environment. Good hosts like WPengine make having a production and staging environment easy. You can control the PHP versions independently. I use WPengine’s git deployment to move my local updates to the staging server. SFTP works, too. If you need database changes, you’ll also need to do a database migration. Core and plugin updates will need a database migration (Don’t forget to change the site URL or you won’t be able to log in!) If you need to do a database migration, use the instructions here
My preferred workflow is to copy the full production site (code + database) to staging, push my code changes, then do the core and plugin upgrades on the server (they often involve database changes), which is when my change list above comes in handy. I don’t like doing database migrations unless I absolutely have to, because with lots of users logging in to the site, data is bound to get out of sync with my local version in a matter of hours. Getting back in sync is tricky, so I choose to avoid the problem altogether by only moving code, keeping my change file, and replaying the steps on the staging server.
If you don’t have a staging environment and can’t get one with your host, or you can’t upgrade the PHP version yourself on your host, then you need a different plan. You’ll need to set up another site on another host that uses PHP 7.2, then put the updated copy of your site there. If you do this,proceed to the alternate #5 below.
Don’t assume everything works. Test it! Use different user account levels (admin, editor, author, contributor, and subscriber). Try every critical function on your site.
Only move on to the next step when you are certain everything works like it should.
5. Deploy to production.
Before you do anything else here, make a back up of your site and your database. Good hosts like WPengine make this easy. If you are doing this manually, verify the backups work locally. You can to be able to roll back if there is an issue.
I planned a maintenance window with my users a few days ahead of time. If you have users who rely on the site, you should, too.
Update your production environment to PHP 7.2, then copy the staging server to the production server. If you are confident that there were no users updating content in between the staging copy above and now, you can copy database and all. If there are changes you don’t want to lose on the production database, you’ll need to use my method and only copy over the theme code, then do core and theme updates on the production site. This is when planned downtime comes in handy.
Alternate deploy (no staging)
If you set up a separate site on 7.2 (not a staging environment of a production site) and it works, then you are ready to cut over to the new version. Configure that new site to use your domain (URL field on the setting page), then point your domain’s DNS records at the new server. If you need to do a database migration, use the instructions here.
6. Verify everything works
Don’t assume everything works. Test it! Use different user account levels (admin, editor, author, contributor, and subscriber). Try every critical function on your site. Use the Debug Info plugin to verify that the PHP change took.
If there are any issues, you might need to roll back to an earlier restore point and PHP version (or point your domain back to your other server), or do some real-time debugging. If your production and staging servers mirror each other in every way except PHP version, you shouldn’t run into anything unexpected. If you do, figure out where the difference is and go back to #3 above.