Automated PHP 5.3 compatibility testing for your (old) code

Update (Mar 5, 2012) : check here for the latest version, supporting PHP 5.4 as well.

Update (Dec 22, 2010) : code has seen some minor modifications to ensure compatibility with the latest PHP_CodeSniffer release (1.3.0RC1) – thanks to Sebastian Bergmann. Also updated the instructions below.

Note (Dec 22, 2010) : this compatibility test will also test all testable cases for 5.0, 5.1 and 5.2

So you or your team has built anywhere between 5 and 500 projects in PHP 4, 5.1 and 5.2 over the past 5 years. And now PHP 5.3 is there, offering a lot of very interesting features, including namespace support, late static binding (finally !), closures, nested exceptions and a bunch more (see the new feature list).

So naturally, you’d like to upgrade. But doing so might break some old code. Why ? Because of some backward incompatibilities :

  • New reserved keywords (goto, namespace)
  • Deprecated functions that will throw an error (the brand new E_DEPRECATED error in fact !)
  • Call-by-value on functions with by-reference parameters will now raise a fatal error
  • and again… many more (see the list)

So how do you ensure your code is PHP 5.3 ready ? Well, there’s a few options.

Option 1 : run your unit tests

You just knew I was going to say that, didn’t you ? Yes, unit tests are still the best way to test the inner working of your code. Although even 100% code coverage will not guarantee a bugfree system ofcourse (some bugs are by design, others by neglect, others…)

Option 2 : test your application

Seems logical, doesn’t it ? Install PHP 5.3 on a separate environment or on your test environment and test the entire application. Ofcourse there are issues for some :

  • Old projects often don’t have any budget allocated for this kind of tedious testing
  • Testing an old project is not easy if the original developers aren’t around anymore… so the testing is best done by the actual user… but you don’t want users to see how their application breaks “because of old code”
  • If you have a lot of projects, testing them one-by-one could take a while… maybe 5.4 will be out by then :p

Option 3 : automate your PHP 5.x compatibility tests

Although the first 2 options are really required to ensure your code is PHP 5.3 ready, using automated tests can get you a long way in detecting deprecated functions, unsupported extensions, etc.

Because I’m in charge of moving about 50 projects to PHP 5.3 in the next few weeks/months, I decided to make at least part of this tedious task a little smoother (and faster).

To use the system, all you need is PHP_CodeSniffer and a new sniff standard I created. You will see errors and warnings popping up if part of the code is not PHP 5.3 compatible.

What’s being tested

  • Deprecated functions
  • Deprecated php.ini directives set via ini_set() or retrieved via ini_get()
  • Deprecated assigning of the return value of new() by reference
  • Prohibited names in function name, class name, namespace name and constant name
  • Magic methods can no longer be private, protected or static
  • Removed, unsupported or deprecated extensions
  • All of the above is being tested for PHP 5.0, 5.1, 5.2 and 5.3 compatibility issues

How to download and install

~ > git clone git://github.com/wimg/PHP53Compat_CodeSniffer.git PHP53Compatibility

  • Copy the PHP53Compatibility directory to {your pear path}/PHP/CodeSniffer/Standards

How to run

Start PHP_CodeSniffer like this :

phpcs --standard=PHP53Compatibility

Sample output

FILE: C:\temp\bla.php
--------------------------------------------------------------------------------

FOUND 15 ERROR(S) AND 2 WARNING(S) AFFECTING 12 LINE(S)
--------------------------------------------------------------------------------

4 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'goto' (since version 5.3)
6 | ERROR | Extension 'dbase' is not available in PHP 5.3 anymore
12 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'const' (since version all)
12 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'const' (since version all)
12 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'const' (since version all)
12 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'const' (since version all)
12 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'const' (since version all)
14 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'do' (since version all)
16 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'goto' (since version 5.3)
18 | ERROR | Function name, class name, namespace name or constant name can
| | not be reserved keyword 'namespace' (since version 5.3)
20 | ERROR | Assigning the return value of new by reference is deprecated in
| | PHP 5.3
31 | ERROR | Magic methods must be public (since PHP 5.3) !
31 | ERROR | Magic methods can not be static (since PHP 5.3) !
36 | ERROR | Extension 'mhash' is not available in PHP 5.3 - use the 'hash'
| | extension instead
42 | ERROR | Extension 'msql' is not available in PHP 5.3 anymore
48 | WARNING | The use of function magic_quotes_runtime() is discouraged
50 | WARNING | The use of ini directive 'safe_mode' is discouraged
--------------------------------------------------------------------------------

Some important notes about the system

  • The system checks for deprecated functions, new reserved keywords and other changes from PHP 5.0 to 5.3. However, it doesn’t check for every incompatibility, only a subset that was easily testable using PHP_CodeSniffer. So you still need to check your application manually to see if it runs properly. However, at least part of the job has been made a little easier.
  • You need to run the tests on a system with PHP 5.3 installed (sounds logical, but seemed like a good idea to mention it…)
  • The tests were written on a sunny afternoon with lots of interruptions, so they’re all but perfect. Please let me know if you find bugs, things missing or just want to flame me 😉

As always, no guarantees that it will do the job… but if you feel it’s of use to you, let me know in the comments !