Posts Tagged ‘php 5.3’

Automated PHP 5.3 compatibility testing for your (old) code

Thursday, June 24th, 2010

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 <path-to-your-PHP-source-directory>

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 !

My personal favorites in PHP 5.3

Tuesday, June 30th, 2009

Just in case you’ve been living on Pluto for the past few days : PHP 5.3 was released today.

My personal favorite new stuff and changes :

  • Nested exceptions : something I’ve wanted for a long time !
  • Namespaces : yes, we finally have them ! Now let’s use them properly (this means : use them were needed, but don’t make everything into a namespace !)
  • str_getcsv function : a useful function if you need to import CSV data that’s not stored in a file
  • SOAP user specified headers : very useful if you have some kind of special authentication needs, session or cookie that need to be set, etc. in your SOAP calls
  • PHAR included by default
  • CURLOPT_PROGRESSFUNCTION : very useful if you’re requesting large URLs… combine it with a nice ajax system and you can provide your customers with a neat progress bar
  • Call-time pass-by-reference is deprecated : good… no more reference abuse there… most people using it don’t know what they’re doing, which leads to all sorts of ‘weird’ situations anway

My least favorite :

  • Goto : I know there’s some cases where it might be useful, but honestly it reminds me of my BBC BASIC days… I’m glad there’s no explicit line numbers in PHP ;-)
  • Short ternary notation : maybe it’s easier to parse (haven’t looked at the code yet), but I don’t think it’s easier to understand, especially for novices… it’s easy for them to get lost with some of these short notations…
  • mysql_db_query is deprecated : yes, I know there are better ways of handling multiple db’s, but sometimes it’s just so easy to get data from one db and insert it in another one without the need for 2 separate links…
  • __DIR__ global constant : seriously, is dirname(__FILE__) so hard that we need a separate global constant for it ? Then again, it’s better than someone not using globals and calling dirname(__FILE__) 50 times…
  • The mode parameter on round : might be useful, except that the manual doesn’t explain what each option does

But, regardless of these few things, it’s yet another step – no, let me rephrase that – milestone in the right direction.

To everyone who worked on PHP 5.3 : great job ! Keep up the good work !