A simple PHP version manager
I have multiple versions of PHP installed with Homebrew on my computer and it has always been a nightmare to use a specific version in the terminal for different commands. For example, installing Composer dependencies with a specific PHP version:
/usr/bin/local/php73 $(which composer) install
I ended up writing a small ZSH function to easily switch from one version to another à la nvm
. It is quite simple under the hood as it simply changes the content of the $PATH
variable so that the php
command points to the desired version.
The function can be used as follows:
# Use a specific version
pvm use 7.4
# Use the system default version
pvm use system
# Try to guess a version from a `composer.json` file up in the folder tree
pvm use
# Display the current version
pvm current
# List available versions
pvm list
pvm ls
The pvm use
command can be used without specifying a version, it will try to find a composer.json
file up in the folder tree and guess a PHP version from its dependencies.
Disclaimer
This is a script created specificly to work on my local environment, I can not guarantee that it will work correctly on any other environment. Use it at your own risk.
The script
You will find the script below, to start using it, add it to your ~/.zshrc
file or create a separate file and add the following to your ~/.zshrc
:
source /path/to/pvm.zsh
You also will need to have multiple versions of PHP installed with Homebrew as well as the jq
CLI:
brew install jq \
shivammathur/php/php \
shivammathur/php/[email protected] \
shivammathur/php/[email protected] \
shivammathur/php/[email protected] \
shivammathur/php/[email protected] \
shivammathur/php/[email protected] \
shivammathur/php/[email protected] \
shivammathur/php/[email protected]
Here is the script:
#!/bin/zsh
# Alias PHP version to Brew versions
function pvm() {
zparseopts -D -E -a opts -verbose::=verbose v::=version -version::=version
VERSION='0.0.2'
brew_prefix=$(brew --prefix)
function log() {
if [[ $verbose ]]; then
echo $1
fi
}
function get_php_bin_path() {
ls -d $brew_prefix/Cellar/php*/$1*/bin
}
function get_php_versions() {
ls -d $brew_prefix/Cellar/php*/* | grep -E -o '/[0-9]+.[0-9]+' | sed -E 's#/##'
}
function set_php_version() {
_current_php_version=$(pvm current)
_current_path=$(get_php_bin_path "$_current_php_version")
_old_path=$(php -r "echo str_replace('$_current_path:', '', '$PATH');")
if [[ -z $1 ]]; then
export PATH="$_old_path"
return
fi
PHP_VERSIONS="$(get_php_versions)"
_version_exists="$(php -r "echo preg_match('/^$1$/m', '$PHP_VERSIONS');")"
if [[ $_version_exists == "0" ]]; then
echo "Could not find PHP version $1, is it installed?";
return
fi
_new_path=$(get_php_bin_path $1)
_old_path=$(php -r "echo str_replace('$_new_path:', '', '$_old_path');")
export PATH="$_new_path:$_old_path"
}
log "pvm@$VERSION"
if [[ $1 == 'current' ]]; then
local PHP_VERSION=$(php -v | grep -Eo 'PHP [0-9]+.[0-9]+')
echo ${PHP_VERSION/PHP /};
return;
fi
if [[ $1 == 'use' ]]; then
if [[ $2 == 'system' ]]; then
log 'use system'
set_php_version
elif [[ -n $2 ]]; then
log "use $2"
set_php_version $2
else
composerjson_path=$(_find_up composer.json | tr -d '[:space:]')
if [[ -a $composerjson_path/composer.json ]]; then
pvm_version=$(cat $composerjson_path/composer.json | jq '.require.php' | grep -Eo '[0-9](.[0-9])?' | head -n 1)
log "use v$pvm_version from composer.json"
if [[ -n $pvm_version ]]; then
set_php_version $pvm_version
return
fi
fi
fi
return
fi
if [[ $1 == 'list' || $1 == 'ls' ]]; then
get_php_versions
return
fi
if [[ $version == '--version' || $version == '-v' ]]; then
echo $VERSION
return
fi;
echo "pvm $VERSION
A fast and simple PHP manager
USAGE:
pvm <SUBCOMMAND>
FLAGS:
-h, --help
Prints help information
-v, --version
Prints version information
SUBCOMMANDS:
current Print the current PHP version
use [version] Change PHP version
list List all available PHP versions [alias: ls]
"
}