Managing Multiple PHP versions via the ondrej/php PPA
Last week, I did some system updates, and then decided to compile the most recent PHP releases. I've used phpbrew to manage multiple PHP releases for a number of years, and having it install a new version is fairly routine.
Except this time, it wasn't. Due to updates I installed, I was getting errors first with compiling the GD extension, then with ext-intl:
-
If you want Freetype support in ext-gd, you are expected to install the package libfreetype-dev. On Ubuntu, this now installs libfreetype6-dev, which no longer includes the
freetype-config
binary that PHP'sconfigure
script uses to determine what features it supports. -
Similarly, ext-intl depends on the package libicu-dev. Ubuntu's package now omits the
icu-config
binary used by PHP to determine feature support.
I searched for quite some time to find packages that would resolve these problems. I could have found the source code and compiled it and linked to that, but that would mean keeping that up-to-date on top of my PHP installs.
I even looked in the ondrej/php PPA, as that repository has multiple PHP versions already, including source packages.
And then I thought: why not try using those instead of phpbrew?
The rest of this post is how I made that work.
I use Ubuntu for my operating system. The instructions I present here should work on any Debian-based system, but your mileage may vary. If you are using an RPM-based system,
yum
will be your friend, but I have no idea how to add repositories in that system, nor ifupdate-alternatives
is available. As such, these instructions may or may not help you.Which is okay. I mainly wrote them to help future me.
Register the PPA
First, I had to add the PPA to the system:
$ sudo add-apt-repository ppa:ondrej/php
Then the usual:
$ sudo apt update
Approach to installation
I first identified the extensions I typically install, matched them to packages in the PPA, and made a list. I knew I'd be installing the same extensions across all PHP versions I wanted, so I figured I could script it a bit.
From there, I executed the following from the CLI:
$ for VERSION in 5.6 7.0 7.1 7.2 7.3;do
for> for EXTENSION in {listed all extensions here};do
for for> sudo apt install php${VERSION}-${EXTENSION}
for for> done
for> done
This grabbed and installed each PHP I needed along with all extensions I wanted.
Switching between versions
To switch between versions, you have two options:
-
Use the version-specific binaries:
/usr/bin/php5.6
,/usr/bin/php7.0
, etc. -
Set a default via
update-alternatives
:$ sudo update-alternatives --set php /usr/bin/php5.6
If you're not sure what you have installed, use:
$ sudo update-alternatives --config php
which will give you a listing, and an ability to select the one to use.
Rootless alternatives
What if you'd rather not be root to switch the default version, though?
Fortunately, update-alternatives
allows specifying alternate config and admin
directories.
Define the following alias in your shell's configuration:
alias update-my-alternatives='update-alternatives \
--altdir ~/.local/etc/alternatives \
--admindir ~/.local/var/lib/alternatives'
Additionally, make sure you add $HOME/.local/bin
to your $PATH
; since
defining $PATH
varies based on the shell you use, I'll leave that for you to
accomplish.
If you open a new shell, the alias will now be available; alternately, source the file in which you defined it to have it take effect immediately.
Once you've done that, you can run the following, based on the PHP versions you've installed:
$ for VERSION in 5.6 7.0 7.1 7.2 7.3;do
for> update-my-alternatives --install $HOME/.local/bin/php php /usr/bin/php${VERSION} ${VERSION//./0}
for> done
This will create alternatives entries local to your own user, prioritizing them by version; as a result, the default, auto-selected version will be the most recently installed.
You can verify this by running update-my-alternatives --config php
:
There are 5 choices for the alternative php (providing $HOME/.local/bin/php).
Selection Path Priority Status
---------------
Truncated by Planet PHP, read more at the original (another 7476 bytes)