In this post of the PHP Modernization Chronicles series, I am focused on the PHP Version upgrade. Upgrading PHP versions can be a project in itself depending on how many major releases are between the subject and target versions. This post discusses my thoughts, considerations, and tools for the PHP version upgrade step of my modernization project.

In the book Modernizing Legacy Applications in PHP, Paul M. Jones presents ‘PHP Version’ as a prerequisite to the modernization process along with revision control, editor or IDE, style guide, and test suite. At a minimum, the PHP version must support autoloading. So, PHP 5.0 or greater is required. For my modernization project, I want to upgrade to PHP 7. As I mentioned in the PHP Modernization Chronicles - Installation post of this series, the webERP installation script checks for PHP version greater than 5.1. So, I have to assume that the scope of any version upgrade issues will be from 5.1 to 7.0.9 (my target version)

Before beginning the PHP version upgrade steps, there are some things to consider regarding existing environments if the project is already in production. The upgrade problem poses some issues related to the concept of refactoring. Making changes to version compatibility issues will likely cause the project not to run in the current environment where the old version of PHP is still in use. So, in order to get the project to the point where it can be deployed to production, the initial PHP upgrade changes need to be completed all in one go. Since it is unlikely that progress of current releases can be stalled waiting on the PHP version upgrade to be completed, work will need to be performed on both the old version code and the upgrade project at the same time.

I think the safest way to do this is to create a fork (or branch depending on the branching model in use) of the project and do all the PHP upgrade work in that fork. That will allow progress to continue in the old version while the upgrade is being performed. Any changes made to the old version can then be pulled into the fork to keep it up to date with new features and bug fixes being implemented in production during the upgrade project. Development and test environments should be set up with the new PHP version so that the upgraded code can go through the same validation and testing procedures as the production code. In this way, the upgrade work is like refactoring in that small changes can be made and tested as the work progresses. It is just never deployed to production (or released) until it is all done. When all the upgrade work is done, one large pull request can be made to the upstream repository/branch where it can be prepared, tested, and released.

It is very important that all urges to do large scale reformatting of files or restructuring in either of the upstream or upgrade repositories are fought with extreme resolve during this process. Changes should be kept to a minimum so that risk exposure to merge conflicts is as small as possible. Focus should be placed on the upgrade project to get it done as quickly as possible to minimize this as well as exposure to other problems such as incompatibilities being reintroduced from the upstream branch or implementation conflicts from upstream with changes made to fix an incompatibility issue.

The first step of any PHP version upgrade effort is to review the documentation. For each major upgrade of PHP, there is a migration plan added to the Appendices of the online PHP Manual. Depending on how many versions behind the subject code base is, this can be a significant undertaking. In my case, there are 6 major version updates between the subject version and my target version.

While there is no substitution for reading the documentation to understand the impact the version upgrade will have on an application, there are a couple of tools that can help quickly identify problems in the code. These are lint and PHPCompatibility.

The first and easiest validation to perform is lint. There is nothing extra to install. Lint is part of the PHP executable. Running the lint check will report syntax errors on code that is incompatible with the new version (e.g. version of PHP executing the lint check) of PHP at compile time. This does not check code for runtime incompatibilities, but it is a good first step. Most IDEs will have a way to configure this to run automatically. But, here is one way to run it manually from the command line.

find . name '*.php' -exec php -l {} \;

The command above will run the lint checker on all files named *.php in all subdirectories of the project. If there are files containing PHP code that have a file extension different than *.php, additional file extensions can be included in the command. The command below includes *.inc files.

find . \( -name '*.php' -o -name '*.inc' \) -exec php -l {} \;

The next tool is PHPCompatibility. It is a compilation of Sniffs for PHP_CodeSniffer that check source code for PHP version compatibility problems via static code analysis. I used this tool in the past to migrate some project from PHP4 to PHP5. It is a great help. The project is active; specifically in the last few months there has been a flurry of activity. I’ll talk more about getting this set up for my PHP Modernization project in the next post.

This post has gotten pretty long, so I’m going to cut it off here. I didn’t talk about the code in this post, but I think it’s important to do some up front thinking about the problem of upgrading before jumping in and trying to find and fix problems. In the next post, I’ll go into how I set these tools up for my modernization project, the problems they helped me find, and how I fixed them. If you have experience with these or any other tools or considerations for PHP version upgrades, please share in the comments.

Share this on: