Ole Markus has posted 1 posts at DZone. View Full User Profile

Concurrently running multiple versions of PHP

01.07.2011
| 1018 views |
  • submit to reddit

Often I am in a situation where I am stuck with the responsibility of some really messy, old code running on some really old version of PHP (well, at least the 5.2 branch). At the same time I am also stuck with some really messy, but highly new and experimental stuff making use of the latest PHP has to offer.

Other times, i am given the responsibility to test if an older system runs on newer versions of PHP, but I still have to make sure I have a working system because any minute, a critical bug in this system has been found, and guess who will have to fix it? That’s right. Yours truly.

For the former scenario I am stuck with a bunch of development boxes, you say? Or virtual machines if I am more lucky, you say? And for the latter scenario, do I have to do a lot of mass upgrades and mass downgrades of PHP packages, extensions and libraries and whatnot?

It so happens that I am running Gentoo. And guess what? Gentoo has support for running multiple minor versions of PHP in parallel!

In fact, these were some of the use cases for rewriting the PHP packages for Gentoo. Most distros seem to support some form of parallel install of major versions of PHP. At least Debian/Ubuntu has the major version of PHP as a part of the package name. You can be the judge if this really means anything now that PHP 4 has gone into oblivion (and so has PHP 6, it seems). Anyways, it is in the minor versions that the PHP extension ABI is broken, and all the new cool features are addded. These are the versions that you want to try to install in parallel.

Anyways, enough tarradiddle. Now I will guide you through how to set up this little piece of magic, step by step, command by command, line change by line change.

Step 1: Emerging PHP

PHP has a huge number of USE flags available. Luckily, the USE flags that the PHP ebuilds set by default are fairly sane so the only one we need to add is the cgi USE flag, which gives us the FastCGI server API. I find that enabling cgi as a global USE flag in /etc/make.conf is a bad idea as I do not care about enabling cgi support for every single package in the tree that support such a thing. If you are like me, adding it to /etc/portage/package.use is what you want. Just drop the following line in there:

dev-lang/php cgi

That is about all the configuration you need for PHP. Now, emerge!

emerge -av php

Step 2: Installing extensions

We all need a few extensions installed. Since we are going to run both PHP 5.2 and PHP 5.3, let us enable building extensions for both as well. Drop the following line into /etc/make.conf

PHP_TARGETS="php5-2 php5-3"

You are probably going to use this system for development, so you will need at least xdebug. You also probably want pecl-memcached. If not, just pick a few other packages to install instead, just for the fun of it.

emerge -av xdebug pecl-memcached

These are the packages that would be merged, in order:

Calculating dependencies... done!

[ebuild N ] dev-php5/xdebug-2.1.0-r1 PHP _TARGETS="php5-2 php5-3" 0 kB [0]

[ebuild N ] dev-php5/pecl-memcached-1.0.2-r2 [1.0.2-r1] USE="session" PHP_TARGETS="php5-2 php5-3" 0 kB [0]

Notice the PHP_TARGETS bit? This is the magic that allows you to build extensions against multiple versions of PHP. You can read more about it in Gentoo PHP documentation.

Step 3: Configuring webservers

Now we are ready to configure some servers. First create some test code. Both server setups will work with the same code. The scenario we want to test now is running two distinct applications on the same server running different versions of PHP.

First create directories /var/www/localhost/php5.2 and /var/www/localhost/php5.3 and put the following script into both of them. Name the files index.php. Feel free to symlink one into the other if you want to save some bytes.

<?php

phpinfo();

Step 3a: Installing and configuring Apache

Apache is a trusted member of the LAMP stack and probably the webserver that the most people are familiar with. In addition to www-servers/apache, we need to install another package to get fastcgi working: www-apache/mod_fastcgi.

So lets install what we need:

emerge apache mod_fastcgi

After all has been installed, simply enable it in /etc/conf.d/apache2:

APACHE2_OPTS="-D DEFAULT_VHOST -D INFO -D LANGUAGE -D USERDIR -D FASTCGI"

I have not found any convenient way of running multiple versions of PHP under the same virtual host, so you will have to set up a few local hostnames. No biggie tho, just put the following into /etc/hosts

127.0.0.1 5-3.localhost 5-2.localhost

Once that is done, drop the following virtual hosts files into /etc/apache2/vhosts.d

/etc/apache2/vhosts.d/5-2.localhost.conf
<VirtualHost *:80>

ServerName 5-2.localhost

DocumentRoot /var/www/localhost/htdocs/php5.2

<IfModule mpm_peruser_module>

ServerEnvironment apache apache

</IfModule>

AddHandler php5-fastcgi .php

FastCgiServer /usr/lib/php5.2/bin/php-cgi

<Directory /var/www/lighttpd/htdocs/php5.2>

Order deny,allow

Allow from all

</Directory>

</VirtualHost>

/etc/apache2/vhosts.d/5-3.localhost.conf
<VirtualHost *:80>

ServerName 5-3.localhost

DocumentRoot /var/www/localhost/htdocs/php5.3

<IfModule mpm_peruser_module>

ServerEnvironment apache apache

</IfModule>

AddHandler php5-fastcgi .php

FastCgiServer /usr/lib/php5.3/bin/php-cgi

<Directory /var/www/lighttpd/htdocs/php5.3>

Order deny,allow

Allow from all

</Directory>

</VirtualHost>

That is it. Now you should be able to enter http://php5-3.localhost/index.php and http://php5-2.localhost/index.php to test your setup.

Step 3b: Installing and configuring Lighttpd

First, make sure that you have the php USE flag enabled in your system. Revisit your /etc/portage/package.use is what and append the following line:

www-server/lighttpd php

Then emerge lighttpd

emerge -av lighttpd

Replace the content of /etc/lighttpd/mod_fastcgi.conf with the following:

server.modules += ("mod_fastcgi")

$HTTP["url"] =~ "^/php5.2/.+\.php$" {

fastcgi.server = ( ".php" => (

"localhost" => (

"socket" => "/var/run/lighttpd/lighttpd-fastcgi-php5-2-" + PID + ".socket",

"bin-path" => "/usr/lib64/php5.2/bin/php-cgi"

)

)

)

}

$HTTP["url"] =~ "^/php5.3/.+\.php$" {

fastcgi.server = ( ".php" => (

"localhost" => (

"socket" => "/var/run/lighttpd/lighttpd-fastcgi-php5-3-" + PID + ".socket",

"bin-path" => "/usr/lib64/php5.3/bin/php-cgi"

)

)

)

}

# vim: set ft=conf foldmethod=marker et :

That is it. Now you should be able to enter http://localhost/php5.2/index.php and http://localhost/php5.3/index.php to test your setup.

Conclusion

I hope that I now have convinced you why you want to run multiple minor versions of PHP in parallel, and how easy it is to setup and configure a system using this feature.

Published at DZone with permission of its author, Ole Markus With.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)