Upgrading PHP, from the trenches
The Web Dev Zone is brought to you in partnership with Mendix. Discover how IT departments looking for ways to keep up with demand for business apps has caused a new breed of developers to surface - the Rapid Application Developer.
It's easy to start new project with PHP 5.4 and 5.5, which have been out for some time. However, jumping to a new version of the PHP interpreter is a leap that must be taken cautiously for medium and large applications, especially in the presence of technical debt (one of my favorite phrases).
Cautiously does not mean with fear: PHP is one of those platforms that improves in support and becomes faster with each new version, so it puts an incentive on you to upgrade.
All your test suites are belong to us
The presence of test suites that can be run on a new environment is fundamental: they can detect the presence of problematic extensions, deprecated functions and new reported errors with the push of a button.
Both unit and acceptance tests work nicely for this goal; even test involving multiple projects as PHP´s automated logging of errors (error_log) will trace any Notices and Array to string conversion.
The largest test suites also provide a basic form of load testing. I became accustomed to measuring the time it takes to run a test suite on different versions of PHP, only to see an improvement with new versions as expected.
I started a new instance on AWS to play around with PHP 5.4: setting up a development environment with some git clone commands, and run all test suites and a few exploratory tests. The test suites should become green again on the new version.
The next step is upgrading CI only. This leaves production with a different version of PHP, so should be only done for a limited period of time. Some CI systems like Travis can easily be configured to run multiple builds on different virtual machines, each with its own PHP version.
The we can upgrade the integration server, where multiple projects are deployed and tested together instead of running their own isolated tests. All projects must be updated to be able to run there.
The first dangerous step is upgrading one of the production servers (or spin up a new dedicated instance on AWS). Redirect not more than 1% or 5% of traffic to it, a standard guinea pig, and check what happens.
When the rate of errors on the guinea pig has been lowered to the same as the standard production environment, we can upgrade them too. The guines pig is useful because there is no way to test and generate the same kind of traffic that production experiences, both qualitativaly (uncovered legacy code or rare input parameters) and quantitatively.
We followed a similar process for upgrading MongoDB, starting from the first servers in the pipeline and bringing forward the change to production, discovering issues gradually.
In the specific
This transition had the goal of bringing us on PHP 5.4. Here are some of the most commoon errors that had to be fixed:
- Array to string conversion, omnipresent in legacy code and that is only raised as an error in the never versions of PHP while it is ignored in old ones.
- The deprecation of old MySQL libraries, such as mysql_*().
- APC that had to be substituted with the new OpCache or an equivalent extension. The cache is shipped in PHP 5.5 but must be installed separately in 5.4 as a PECL extension.
- All extensions had to be checked and rebuilt too, with the same version: for example mongo, memcache, ssh. The API version of PHP is different so the newer versions are compiled into a different folder then the original one, and you will need to adjust absolute paths of zend_extensions. To switch to the new API version, remember to upgrade the php5-dev package too (if you're installing through a package manager).
The good surprise is that while projects with several years on their shoulders necessitated intervention, newer projects (1 year of life) ran flawlessly, just faster. Maybe it's true that code rots.
Moreover, the performance improvement on the test suites (which are representative of the most common and frequent use cases) ranged from 3:1 on the slowest machines to 1.5:1 on the fastest ones. This definitely makes the case for upgrading, and now I'm curious to find out if PHP 5.5 provides other improvements...