After using phpbrew to manage my local PHP versions for a while, I got tired of re-compiling PHP after every release and decided to install multiple PHP versions side-by-side with Ondřej Surý's PPA. One of the features I missed from phpbrew
was the ability to run a command like phpbrew use php-7.2.8
to automatically change the php
command to that version, so I ended up implementing this feature myself using symlinks and shell aliases.
Switching PHP Versions
By default, Ubunutu creates a symlink at /etc/alternative/php
which points to an executable like /usr/bin/php5.6
. I therefore wanted to create my own shell alias to change that symlink by simply running a command like php72
However, /etc/alternative/php
is for the whole system, and I'd have to use sudo
everytime I wanted to change that symlink (or change permissions in /etc/alternative
). But, since I'm the only user on my laptop, I instead hard-coded a symlink from /etc/alternative/php
to another symlink in my home directory:
Now my aliases can simply update that /home/codell/.php
symlink without needing sudo! Here's the full list of aliases which I dropped inside of my ~/.zshrc
file:
alias php56="ln -sf /usr/bin/php5.6 /home/codell/.php && php -v"
alias php70="ln -sf /usr/bin/php7.0 /home/codell/.php && php -v"
alias php71="ln -sf /usr/bin/php7.1 /home/codell/.php && php -v"
alias php72="ln -sf /usr/bin/php7.2 /home/codell/.php && php -v"
Now I can simply run php7.2
or any other version number to make php
alias to that specific version!
(This approach also works perfectly fine if you use bash instead of zsh - just drop your aliases into ~/.bashrc
instead.)
Automating This Based on composer.json
But let's take this one step further - most of the projects I work on have a PHP constraint in their composer.json
file:
{
"name": "some/project",
"require": {
"php": ">=7.1"
}
}
It would be awesome if my shell could automatically switch PHP versions for me based on what that project uses - so that's exactly what I implemented for zsh!
autoload -U add-zsh-hook
change-php-version() {
if [ -f composer.json ]; then
PHPVERSION=$(cat composer.json | jq '.require.php' | grep -o '[0-9].[0-9]')
if [ ! -z "$PHPVERSION" ] && [ -e "/usr/bin/php$PHPVERSION" ]; then
ln -sf "/usr/bin/php$PHPVERSION" /home/codell/.php
php -v | head -n 1 | awk '{print $1 " " $2}'
fi
fi
}
add-zsh-hook chpwd change-php-version
I simply dropped that into my ~/.zshrc
file. Now, whenever I cd
into a different project directory, zsh checks my composer.json
and switches to that PHP version automatically! It also outputs which version it switched to:
It's not perfect though, as it doesn't actually parse the constraint - it does a dumb regex match and assumes whatever x.y
version it sees is what you want. If your constraint was something like >7.0
it would think you wanted 7.0
! However, none of my projects have constraints like that, so I'm not too concerned. Perhaps in the future I'll make this smarter.
Enjoy this article?
Support my open-source work via Github or follow me on Twitter for more blog posts and other interesting articles from around the web. I'd also love to hear your thoughts on this post - simply drop a comment below!