Testing Your Codebase for the PHP7 Migration

Published on May 9, 2017

We are preparing to upgrade the Departmental Web Hosting Environment to PHP 7.0 within the next month.  Knowing that there are at least a few backwards incompatible changes between PHP 5.X and 7.0, the thought of combing through tens of thousands of lines of code is enough to cause a panic attack.  Thankfully, it doesn't have to be a horrifying process.  There are several tools that can be used to assist you in pinpointing areas that might have issues under PHP7.  In addition, you can use these tools today to start evaluating your code; you don't have to wait until PHP7 is available on the -dev servers.

It should be noted that all of these tools can be run on your local machine. If you're on a Mac, you can probably follow the directions here and be up and running.  If you're on a PC, you'll need to either have php installed and running, or bring up a virtual machine that has php installed.


First is PHP 7 Compatibility Checker (major hat-tip to Matt Stanley for letting me know about this package).  The easiest way to use it in our environment is with the phar version of php7cc.  After you've logged into your account (via ssh), navigate to somewhere above your web root.  The php7cc.phar is a single file, so if you want you can place it into the directory immediately above your www directory.  Next, use wget to retrieve php7cc.phar from github


wget https://github.com/sstalle/php7cc/releases/download/1.1.0/php7cc.phar


wget should download the file and report that it successfully saved php7cc.phar.  Now we're ready to have it test our codebase.  Using it is pretty straightforward: execute it giving it the path to the code you want to have checked.  As an example, if I have php7cc.phar saved in the directory above my www directory and i want it to scan the code in one of my WordPress plugins, I can do

[bash]php php7cc.phar www/wp-content/plugins/mizzoumvc/[/bash]

It should then generate a report identifying all possible compatibility issues.  In the report it will list the file, line number and the potential issue.

[php] File: /var/www/html/foo.missouri.edu/www/wp-content/plugins/mizzoumvc/library/Main.php -> Line 127: Possible array element creation during by-reference assignment $this->aryRenderData['MainPost'] =& $this->aryRenderData['objMainPost']; -> Line 141: Possible array element creation during by-reference assignment $this->aryRenderData['Site'] =& $aryContext['objSite']; -> Line 302: Function argument(s) returned by "func_get_args" might have been modified func_get_args(); [/php]


It is very possible that it will generate false-positives, so you will need to dig into the code to verify the issues it identified.  If you don't want to read the report in the terminal screen, you can have it save it to a file.

[bash] php php7cc.phar www/wp-content/plugins/mizzoumvc/ > php7cc-report.txt [/bash]


Alternatively, there is a docker container for php7cc you can use if you'd prefer to test locally and either don't want to install php7cc locally or don't have php installed.

PHP 7 Migration Assistant Report (MAR)

Next up is the PHP7 Migration Assistant Report.  There is no phar available, so you'll need to either clone the repository, or download the zip archive from github and then extract the contents. For running on our environment, from the directory above my www, I'll clone the repository

[bash]git clone https://github.com/Alexia/php7mar.git[/bash]

This will clone the repository's contents into a php7mar directory.  Move into that directory.  To have it begin the analysis, do

[bash]php mar.php -f="/var/www/html/foo.missouri.edu/www/wp-content/plugins/mizzoumvc"[/bash]

Once finished, php7mar will indicate that is saved a report. By default, it generates a markdown-based report (named by date) into a reports directory.

[php] 2017-05-08T20:59:30+00:00 Scanning /var/www/html/foo.missouri.edu/www/wp-content/plugins/mizzoumvc Including file extensions: php ERROR! Syntax checking was selected and a PHP binary lower than 7.0.0-dev was specified. Processed 28055 lines contained in 310 files. Processing took 33.93580698967 seconds.









*note - php7mar does support an -r option that allows you to identify a different location to save the report.

You'll notice that php7mar's report picked up issues that are commented out in the source code, and also picked up a few issues that php7cc did not.  In addition, it did not flag some possible issues that php7cc identified.  This is why it's always good to run a couple of different tests on your source code.


It's entirely possible that your IDE already has PHPCodeSniffer with the PHPCompatibility standard installed.  You'll need to check your IDE's documentation to see if it comes with CodeSniffer, or if you can add it in as a plugin/module. In PHPStorm, you can access it by right-clicking on the project, Inspect Code, Inspection Profile, click the ellipsis button. From there, scroll down to PHP --> Probable Bugs, and make sure PHP 7 Compatibility is checked.

If you decide to download CodeSniffer directly, please note that CodeSniffer 3.0 (released this week) introduced breaking changes and PHPCompatibility has not yet been updated.  You'll need to make sure you download the 2.9 branch.  I plan on doing a follow-up guide on installing and using PHPCodeSniffer+PHPCompatibility tomorrow.

Fixing the Code

Now the fun part begins: checking the identified areas and making corrections.  Using my examples from above, the error "Possible array element creation during by-reference assignment" refers to the backwards incompatible change "Array ordering when elements are automatically created during by reference assignments has changed." In the case of my example code, the order of the array elements does not matter, and will not affect the expected behavior once we move to PHP7.  The error "Function argument(s) returned by 'func_get_args' might have been modified" refers to the backwards incompatibility "Functions inspecting arguments report the current parameter value."  This one I'll definitely need to double-check and make sure I'm not affecting the parameter values before calling func_get_args().

Of course everyone's code is going to be different, and I'm positive you'll come across different notices.  If you run into some you don't understand, or are having a hard time figuring out reach out to the campus web dev community! We're here to help each other.  If you don't feel comfortable asking the group-at-large, reach out to me directly.  We want this migration to be as smooth and as transparent as possible to all of our end-users, and will do whatever we can to make that happen.