Skip to content

Instantly share code, notes, and snippets.

@rhukster
Last active March 30, 2024 10:41
Show Gist options
  • Save rhukster/f4c04f1bf59e0b74e335ee5d186a98e2 to your computer and use it in GitHub Desktop.
Save rhukster/f4c04f1bf59e0b74e335ee5d186a98e2 to your computer and use it in GitHub Desktop.
Easy Brew PHP version switching (Now moved to https://github.com/rhukster/sphp.sh)
#!/bin/bash
# Creator: Phil Cook
# Modified: Andy Miller
#
# >>> IMPORTANT: Moved to: https://github.com/rhukster/sphp.sh
# >>> Kept here for legacy purposes
#
osx_major_version=$(sw_vers -productVersion | cut -d. -f1)
osx_minor_version=$(sw_vers -productVersion | cut -d. -f2)
osx_patch_version=$(sw_vers -productVersion | cut -d. -f3)
osx_patch_version=${osx_patch_version:-0}
osx_version=$((${osx_major_version} * 10000 + ${osx_minor_version} * 100 + ${osx_patch_version}))
homebrew_path=$(brew --prefix)
brew_prefix=$(brew --prefix | sed 's#/#\\\/#g')
brew_array=("5.6","7.0","7.1","7.2","7.3","7.4","8.0","8.1","8.2")
php_array=("[email protected]" "[email protected]" "[email protected]" "[email protected]" "[email protected]" "[email protected]" "[email protected]" "[email protected]" "[email protected]")
php_installed_array=()
php_version="php@$1"
php_opt_path="$brew_prefix\/opt\/"
php5_module="php5_module"
apache_php5_lib_path="\/lib\/httpd\/modules\/libphp5.so"
php7_module="php7_module"
apache_php7_lib_path="\/lib\/httpd\/modules\/libphp7.so"
php8_module="php_module"
apache_php8_lib_path="\/lib\/httpd\/modules\/libphp.so"
native_osx_php_apache_module="LoadModule ${php5_module} libexec\/apache2\/libphp5.so"
if [ "${osx_version}" -ge "101300" ]; then
native_osx_php_apache_module="LoadModule ${php7_module} libexec\/apache2\/libphp7.so"
fi
# Has the user submitted a version required
if [[ -z "$1" ]]; then
echo "usage: sphp version [-s|-s=*] [-c=*]"
echo
echo " version one of:" ${brew_array[@]}
echo
exit
fi
php_module="$php5_module"
apache_php_lib_path="$apache_php5_lib_path"
simple_php_version=$(echo "$php_version" | sed 's/^php@//' | sed 's/\.//')
if [[ simple_php_version -ge 70 && simple_php_version -lt 80 ]]; then
php_module="$php7_module"
apache_php_lib_path="$apache_php7_lib_path"
elif [[ simple_php_version -ge 80 ]]; then
php_module="$php8_module"
apache_php_lib_path="$apache_php8_lib_path"
fi
apache_change=1
apache_conf_path="$homebrew_path/etc/httpd/httpd.conf"
apache_php_mod_path="$php_opt_path$php_version$apache_php_lib_path"
# What versions of php are installed via brew
for i in ${php_array[*]}; do
version=$(echo "$i" | sed 's/^php@//')
if [[ -d "$homebrew_path/etc/php/$version" ]]; then
php_installed_array+=("$i")
fi
done
# Check that the requested version is supported
if [[ " ${php_array[*]} " == *"$php_version"* ]]; then
# Check that the requested version is installed
if [[ " ${php_installed_array[*]} " == *"$php_version"* ]]; then
# Switch Shell
echo "Switching to $php_version"
echo "Switching your shell"
for i in ${php_installed_array[@]}; do
brew unlink $i
done
brew link --force "$php_version"
# Switch apache
if [[ $apache_change -eq 1 ]]; then
echo "Switching your apache conf"
for j in ${php_installed_array[@]}; do
loop_php_module="$php5_module"
loop_apache_php_lib_path="$apache_php5_lib_path"
loop_php_version=$(echo "$j" | sed 's/^php@//' | sed 's/\.//')
if [[ loop_php_version -ge 70 && loop_php_version -lt 80 ]]; then
loop_php_module="$php7_module"
loop_apache_php_lib_path="$apache_php7_lib_path"
elif [[ loop_php_version -ge 80 ]]; then
loop_php_module="$php8_module"
loop_apache_php_lib_path="$apache_php8_lib_path"
fi
apache_module_string="LoadModule $loop_php_module $php_opt_path$j$loop_apache_php_lib_path"
comment_apache_module_string="#$apache_module_string"
# If apache module string within apache conf
if grep -q "$apache_module_string" "$apache_conf_path"; then
# If apache module string not commented out already
if ! grep -q "$comment_apache_module_string" "$apache_conf_path"; then
sed -i.bak "s/$apache_module_string/$comment_apache_module_string/g" $apache_conf_path
fi
# Else the string for the php module is not in the apache config then add it
else
sed -i.bak "/$native_osx_php_apache_module/a\\
$comment_apache_module_string\\
" $apache_conf_path
fi
done
sed -i.bak "s/\#LoadModule $php_module $apache_php_mod_path/LoadModule $php_module $apache_php_mod_path/g" $apache_conf_path
echo "Restarting apache"
brew services stop httpd
brew services start httpd
fi
echo ""
php -v
echo ""
echo "All done!"
else
echo "Sorry, but $php_version is not installed via brew. Install by running: brew install $php_version"
fi
else
echo "Unknown version of PHP. PHP Switcher can only handle arguments of:" ${brew_array[@]}
fi
@dregad
Copy link

dregad commented Jan 3, 2023

I'm using GNU grep as default instead of MacOS's version of it, and since it was upgraded to 3.8, sphp started throwing warnings (8 per installed php version):

grep: warning: stray \ before /

I understand that the backslash is required as the regex is also used for sed, so I'm not quite sure how best to fix this. As a workaround I've modified sphp to call /usr/bin/grep.

@jpickwell
Copy link

jpickwell commented Jan 3, 2023

@dregad, in addition to that change, I would remove the unnecessary escapes in the variable values altogether, and then do localized replacements for the sed calls by using something like ${apache_php_mod_path//\//\\\/} (the general form is ${VAR//PATTERN/REPLACE}).

Using the full path for every non-built-in command creates predictability in the script and reduces inconsistencies between user machines.

To help with consistency and to reduce maintenance, small wrapper functions can be written inside the script for each non-built-in. For example:

grep() {
  /usr/bin/grep "$@"
}

Then grep can be used without a path or backslash prefix in the rest of the script.

I would also run the script through ShellCheck and shfmt.

@rhukster
Copy link
Author

rhukster commented Jan 3, 2023

If anyone wants to rewrite the script and optimize it, I will gladly test it!

@dregad
Copy link

dregad commented Jan 4, 2023

@rhukster thanks for considering this as a permanent change to sphp script.

Since Gists do not allow pull requests, how would you like to receive contributions ? Is a simple comment here with a patch OK, or would you prefer to get the changes from a fork of the Gist ?

@rhukster
Copy link
Author

rhukster commented Jan 4, 2023

I might just move this to a full repo. Overkill for one file generally but in these situations PRs and issues would be helpful.

Let me do that today.

@dregad
Copy link

dregad commented Feb 22, 2023

@rhukster just wondering if you ever got around to creating a repo for this script to allow contributions via pull requests. If so, a link would be nice as I didn't find it.

@rhukster
Copy link
Author

Dang forgot all about it.. going to create that repo now.

@rhukster
Copy link
Author

@rhukster just wondering if you ever got around to creating a repo for this script to allow contributions via pull requests. If so, a link would be nice as I didn't find it.

Here it is: https://github.com/rhukster/sphp.sh

@dregad
Copy link

dregad commented Mar 6, 2023

Thanks @rhukster. FYI you forgot to update a link in your blog article, PHP Switcher Script in the paragraph after the subtitle still points to Gist.

@rhukster
Copy link
Author

rhukster commented Mar 6, 2023

cheers, will update that too.

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