Linux Devbox: Running multiple PHP versions

Ever since PHP5 came out, there is some need to run multiple PHP versions on your local development box, or at least make it easy to switch from one version to another. Derick Rethans has posted a solution based on your PATH environment variable. I have devised an alternative approach which changes the system wide used PHP version.

1. Compiling and installing

First, if you’re used to installing PHP from your distro’s repositories, stop with that. Remove your current version with your package manager entirely, deleting it’s configuration as well (maybe backing it up in your homedir, if it’s very special).

Now, download the PHP version of your liking into a local directory, maybe in your homedir, or (what I prefer) in /usr/local/src, and extract it (changing your mirror accordingly):

$ cd /usr/local/src && \
    wget http://nl3.php.net/get/php-5.3.3.tar.bz2/from/this/mirror -O - \
    | tar jx

Change into the extracted source directory

$ cd php.5.3.3

and configure the installation with all the flags you need for your specific version, and make sure you choose a prefix somewhere in /usr/local/, that would not affect any future installed versions. I prefer /usr/local/php/5.x.x/, and have one base php.ini in /usr/local/etc/, and additional php.ini’s per version in /usr/local/etc/php/5.x.x/, so the configure command would read something like:

$ ./configure                                              \
    --prefix=/usr/local/php/5.3.3                                \
    --with-config-file-path=/usr/local/etc/php                   \
    --with-config-file-scan-dir=/usr/local/etc/php/5.3.3.d       \
    --with-mysql                                                 \
    --with-mysqli                                                \
    --with-pdo-mysql                                             
    # etcetera

Note that once you configured, the configure script will write out a file called config.nice which will contain all chosen flags and options. You can edit it or run it with additional flags to reconfigure your installation.

If you have established that the configuration is correct and you have all the flags and additional settings you need, you can start compiling and installing.

$ make -j5 # I use 5 for my quadcore, use 3 for dualcore
$ sudo make install

Repeat the above for any other versions of PHP you might want. I currently have 5.2.14 and 5.3.3, but you can use different version names, for example for versions you have running with or without XDebug, GD, suhosin patches, or whatever, with some identifying suffix, e.g. php5.3.3-suhosin

2. Getting the php-version.sh script

The script is published at my github. Download it in a sensible place and chmod it so it can be run:

$ cd /usr/local/bin && \
    wget http://github.com/drm/snippets/raw/master/shell/php-version.sh && \
    chmod +x ./php-version.sh

3. Using the script

Run the script with the chosen PHP version as an argument (like 5.3.3 in the example above). The first time run, it needs the --force flag to force switching to that version. See further down this post for more information.

$ php-version.sh 5.3.3 --force

Now, the script symlinks all files in the PHP’s bin directory to /usr/local/bin/. Validate your status with php -v which should print the current php version as follows.

$ php -v
PHP 5.3.3 (cli) (built: Oct 30 2010 14:26:40) 
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

Whenever you switch a version, it checks to see what the current symlinked version is, removing all symlinks to the current version and symlinking again to the new version specified. So any successive call to the script may lack the --force option, since the current PHP version should be detected. Running the script without arguments prints a usage message, and the currently detected PHP version:

$ php-version.sh
Usage: /usr/local/bin/php-version.sh {version [--force]|--off}
Current version: 5.3.3

Remove the symlinks without choosing a new version is done by passing the --off flag as a first parameter

$ php-version.sh --off
$ php -v
bash: php: command not found

4. Building and using PHP extensions

Whenever you need to build extensions (like XDebug, which is pretty useful), you will need to switch to the version you’re building for, before running phpize. After all, the symlinked version of phpize would be used to detect your PHP environment. Installing the extension will need some handywork, but as long as you keep your prefixes separated clearly, you shouldn’t get into any trouble. Just install the extensions in the correct place aside the version you compiled for.

Since each version checks for it’s own configuration files in the directory specified with the --with-config-file-scan-dir configure option, you can put the extension and zend_extension directives in files placed in that directory.

$ echo "extension=/path/to/extension.so" >> /usr/local/etc/php/5.3.3.d/myextension.ini
$ php -i | grep myextension.ini
additional .ini files parsed => /usr/local/etc/php/5.3.3.d/myextension.ini

5. Web server configuration

I have started switching my development boxes from Apache with mod_php5 to nginx with fastcgi, which makes it a bit easier to switch the php version used by your web server, since the fast cgi is most easily started up by using the php cli binary itself.

The easiest setup for nginx and php fast cgi is described by Tomasz Sterna here.

If you’re still keen on using Apache, either consider switching to mod_fastcgi in stead of mod_php5, symlink the installed libphp5.so by hand, or augment the php-version.sh script to do it for you.

Happy php’ing 🙂

Original post at drm.tweakblogs.net

This entry was posted in Development, Linux & BSD and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Subscribe without commenting