Skip to content

Instantly share code, notes, and snippets.

@w00fz
Last active February 7, 2022 00:12
Show Gist options
  • Save w00fz/142b6b19750ea6979137b963df959d11 to your computer and use it in GitHub Desktop.
Save w00fz/142b6b19750ea6979137b963df959d11 to your computer and use it in GitHub Desktop.
PHP switcher
#!/bin/bash
# Check if command was ran as root.
if [[ $(id -u) -eq 0 ]]; then
echo "The command \"sphp\" should not be executed as root or via sudo directly."
echo "When a service requires root access, you will be prompted for a password as needed."
exit 1
fi
# Usage
if [ $# -ne 1 ]; then
echo "Usage: sphp [phpversion]"
echo "Versions installed:"
brew list | grep '^php[0-9]\{2,\}$' | grep -o -E '[0-9]+' | while read -r line ; do
echo " - phpversion: $line"
done
exit 1
fi
currentversion="`php -r \"error_reporting(0); echo str_replace('.', '', substr(phpversion(), 0, 3));\"`"
newversion="$1"
majorOld=${currentversion:0:1}
majorNew=${newversion:0:1}
minorNew=${newversion:1:1}
brew list php$newversion 2> /dev/null > /dev/null
if [ $? -eq 0 ]; then
echo "PHP version $newversion found"
# Check if new version is already the current version.
# if [ "${newversion}" == "${currentversion}" ]; then
# echo -n "PHP version ${newversion} is already being used. Continue by reloading? (y/n) "
# while true; do
# read -n 1 yn
# case $yn in
# [Yy]* ) echo && break;;
# [Nn]* ) echo && exit 1;;
# esac
# done
# fi
echo "Unlinking old binaries..."
brew unlink php$currentversion 2> /dev/null > /dev/null
echo "Linking new binaries..."
brew link php$newversion
echo "Linking new modphp addon..."
sudo ln -sf `brew list php$newversion | grep libphp` /usr/local/lib/libphp${majorNew}.so
echo /usr/local/lib/libphp${majorNew}.so
echo "Fixing LoadModule..."
apacheConf=`httpd -V | grep -i server_config_file | cut -d '"' -f 2`
sudo sed -i -e "/LoadModule php${majorOld}_module/s/^#*/#/" $apacheConf
if grep "LoadModule php${majorNew}_module .*php${newversion}" $apacheConf > /dev/null
then
sudo sed -i -e "/LoadModule php${majorNew}_module .*php${newversion}/s/^#//" $apacheConf
else
sudo sed -i -e "/LoadModule php${majorNew}_module/s/^#//" $apacheConf
fi
echo "Updating version file..."
pgrep -f /usr/sbin/httpd 2> /dev/null > /dev/null
if [ $? -eq 0 ]; then
echo "Restarting system Apache..."
sudo pkill -9 -f /usr/sbin/httpd
sudo /usr/sbin/apachectl -k restart > /dev/null 2>&1
fi
pgrep -f /usr/local/"Cellar|opt"/*/httpd 2> /dev/null > /dev/null
if [ $? -eq 0 ]; then
echo "Restarting homebrew Apache..."
sudo pkill -9 -f /usr/local/"Cellar|opt"/*/httpd
sudo /usr/local/bin/apachectl -k restart > /dev/null 2>&1
fi
# pgrep -x httpd 2> /dev/null > /dev/null
# if [ $? -eq 0 ]; then
# echo "Restarting non-root homebrew Apache..."
# httpd -k restart > /dev/null 2>&1
# fi
echo "Done."
# Show PHP CLI version for verification.
echo && php -v
else
echo "PHP version $majorNew.$minorNew was not found."
echo "Try \`brew install php${newversion}\` first."
exit 1
fi
@w00fz
Copy link
Author

w00fz commented Nov 7, 2016

@wimleers I'm not sure what PHP_INI_SCAN_DIR is useful for but I can add it if you tell me where that should go

@crecabar I don't need to do that with homebrew. When the PHP version changes, it is applied globally. I use zsh though.

@moismailzai
Copy link

moismailzai commented Apr 5, 2017

Great script, I've added a few modifications here: https://gist.github.com/moismailzai/765007c45f908085ec5807e4463606b1

Specifically, I've added a symlink to the currently active php.ini and am running tests for orphaned conf.d/*.ini files that are leftover by uninstalled modules and which cause php CLI to complain (thanks @benkmugo for the sed regex!). I've also added a check for homebrew mariadb, which gets stopped by the switching script and needs to be restarted. Feel free to include any of that in your gist.

PS, I don't think the check you do on line 73 is working correctly:

pgrep -f /usr/local/"Cellar|opt"/*/httpd 2> /dev/null > /dev/null

It looks like everything after "Cellar|opt" is being ignored (so the code block always runs). You can test in console:

Correctly yields 0 (non error status):

pgrep -f /usr/local/"Cellar|opt"/*/httpd 2> /dev/null > /dev/null    
echo $?

Incorrectly yields 0 (because no such process exists):

pgrep -f /usr/local/"Cellar|opt"/*/SOMETHINGTHATDOESNTEXIST 2> /dev/null > /dev/null    
echo $?    

Correctly yields 1 (error status):

pgrep -f /usr/localSOMETHINGTHATDOESNTEXIST/"Cellar|opt"/*/httpd 2> /dev/null > /dev/null    
echo $?

@yushine
Copy link

yushine commented Aug 31, 2017

Good job. Thanks.

Copy link

ghost commented Oct 13, 2017

hi there. thanks for this great script. i used it thankfully the last years... but with the latest brew i experienced some troubles, so what i am thinking about is: with sierra and high sierra i do not use the built in apache anymore, as it is said here: https://getgrav.org/blog/macos-sierra-apache-multiple-php-versions

so i am using the brew httpd and brew does not want to start httpd with sudo or at least its not recommended.
so i modified the parts in this script here to stop and start apache with "brew services start httpd" and "brew services stop httpd"... in this script u are restarting it with sudo... when listing "brew services list", the httpd service is marked yellow...

didnt u experience some problems? wouldnt it be better to restart the brew apache with "brew services stop httpd" and "brew services start httpd"?

@jdoubleu
Copy link

jdoubleu commented Dec 1, 2017

For macOS users this script might act a bit different.

The sed in macOS requires a suffix for the in-place option -i (see https://linux.die.net/man/1/sed).
It creates a file named httpd.conf-e because it uses the -e option as suffix argument.
Just change line 55 to:
sudo sed -i '' -e "/LoadModule php${majorOld}_module/s/^#*/#/" $apacheConf

@narnigrin
Copy link

Hint for macOS High Sierra users: If you run into /usr/local/sbin is not writeable errors, check that your /usr/local/sbin actually exists. If not, just creating it and chowning it to your user solves the problem.

@vukanac
Copy link

vukanac commented Apr 20, 2018

    # Remove from PATH - ALL
    sed -i '' "/[email protected]/d" "$HOME/.zshrc"
    sed -i '' "/[email protected]/d" "$HOME/.zshrc"
    # Add new to PATH
    echo 'export PATH="$(brew --prefix '"$php_version"')/bin:$PATH"' >> "$HOME/.zshrc"

@maskedjellybean
Copy link

Thank you for this script! Unfortunately it isn't changing the PATH for me, and so only Apache PHP is changed and not CLI PHP. I use zsh and Homebrew PHP. Based on the comments above this is supposed to work, but for me it just doesn't.

I came up with this Bash function to call instead of sphp. It calls sphp and then finds the PATH within .zshrc and replaces it:

function switch_php() {
	CURR_PHP_VERSION=$(php -v | tail -r | tail -n 1 | cut -d " " -f 2 | cut -c 1-3)
	NEW_PHP_VERSION=$1

	if [ "$CURR_PHP_VERSION" = "$NEW_PHP_VERSION" ]; 
	then
		echo "Already on $NEW_PHP_VERSION ya idiot."
	else
		echo "Switching from $CURR_PHP_VERSION to $NEW_PHP_VERSION."

		sphp $NEW_PHP_VERSION

		sed -i '' "s/php@$CURR_PHP_VERSION/php@$NEW_PHP_VERSION/g" "$HOME/.zshrc"
		
		source ~/.zshrc

		echo "New CLI PHP:"
		php -v

	fi
}

Call it like so: switch_php 7.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment