Note: this workflow is a general guide. Use your judgement based on your specific use case.

Environments

Set up two environments to run the code: the current version, and the one to which you want to upgrade. We'll refer to these environments as "baseline" and "upgrade" respectively. They should be as similar as possible, except for the PHP version. You may encounter problems at this stage:

  • Extension not available for the new PHP version: you may have to switch to an alternative extension; there are suggestions in this guide.

Error Reporting

Enable all error reporting, including notices. This is important because many of these notices will become warnings or even fatal errors in newer PHP versions. By suppressing notices, you would only make it harder to debug compatibility issues.

Incompatibilities

A great way to find incompatibilities is to use an automated tool called PHPCompatibility. It will scan your code and will give you a comprehensive report of the problems that it has found.

If you run it with the -s flag, then the report will also give you the names of the sniffs, which your can use to navigate the list of incompatibilities.

For example:

vendor/bin/phpcs -s

will output a report with the sniff name in parentheses:

(PHPCompatibility.Operators.ChangedConcatOperatorPrecedence.Found)

Please note that despite PHPCompatibility being an amazing tool, it does not replace thorough testing. It does not guarantee to detect every possible problem, nor can it vouch for the correctness of your fixes.

Testing

With Automated Tests

  1. Run the tests on the baseline environment to confirm that they are still trustworthy. It's possible for a test suite to have been green a year ago and stop working today due to flaky tests.
  2. If your test suite is not green, it would make sense to fix any issues before undertaking an upgrade, so that you may safely rely on your tests.
  3. Run the tests on the upgrade environment. It's quite possible that despite issues reported by PHPCompatibility, your tests may pass. This is because PHPCompatibility scans code regardless of whether it's being used by the application or not. You might have library features that you simply don't use or methods in your own code that you don't call from anywhere.
  4. Fix the issues that cause your tests to fail and run them again. Repeat until the test suite is green.

Without Automated Tests

Tip: it would be prudent to write an automated test suite before undertaking a PHP upgrade; at the very least, a high-level acceptance test suite would be invaluable to ensure a successful upgrade.

  1. Thoroughly test on the baseline environment to be able to distinguish pre-existing bugs from ones caused by the upgrade.
  2. Fix any pre-existing issues before undertaking the upgrade. Having issues due to mixed causes would make it much more difficult to debug.
  3. Thoroughly test on the upgrade environment.
  4. Fix issues that cause any kind of message to be reported by PHP, or cause any change in the behavior of your application. It's quite possible that after everything is working, PHPCompatibility would still report issues. This is because PHPCompatibility scans code regardless of whether it's being used by the application or not. You might have library features that you simply don't use or methods in your own code that you don't call from anywhere.

Remaining PHPCompatibility Issues

If some issues went unaddressed despite a successful upgrade, you may choose to ignore them in the code analysis. You can achieve that by creating a phpcs.xml file such as this one:

<?xml version="1.0"?>
<!-- see: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset -->
<ruleset>

    <!-- Allow specific extensions, as to not scan files that don't have any PHP in them -->
    <arg name="extensions" value="php,inc,html,tpl"/>

    <autoload>vendor/phpcompatibility/php-compatibility/PHPCSAliases.php</autoload>

    <!-- Exclude a folder -->
    <exclude-pattern>../.svn/*</exclude-pattern>

    <!-- Exclude a file -->
    <exclude-pattern>../classes/myUser.orig.php</exclude-pattern>

    <!-- Ignore empty files, should you be required to keep them -->
    <rule ref="Internal.NoCodeFound">
        <severity>0</severity>
    </rule>

    <!-- Ignore mixed line endings, should fixing them cause other problems -->
    <rule ref="Internal.LineEndings.Mixed">
        <severity>0</severity>
    </rule>

    <!-- Disable a sniff -->
    <rule ref="PHPCompatibility">
        <exclude name="PHPCompatibility.Miscellaneous.RemovedAlternativePHPTags"/>
    </rule>

    <!-- Disable a sniff, but only for certain files -->
    <rule ref="PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore">
        <exclude-pattern>../lib/pear/PHPUnit-3.4.9/*</exclude-pattern>
    </rule>
</ruleset>

Tips

  • When fixing compatibility issues, we strongly recommend to use source control and make a commit after every type of change for easier debugging later.