Skip to content

Instantly share code, notes, and snippets.

@rhukster

rhukster/sphp.sh

Last active May 24, 2021
Embed
What would you like to do?
Easy Brew PHP version switching
#!/bin/bash
# Creator: Phil Cook
# Modified: Andy Miller
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}))
brew_prefix=$(brew --prefix | sed 's#/#\\\/#g')
brew_array=("5.6","7.0","7.1","7.2","7.3","7.4","8.0")
php_array=("php@5.6" "php@7.0" "php@7.1" "php@7.2" "php@7.3" "php@7.4" "php@8.0")
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="/usr/local/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 "/usr/local/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
@sgotre

This comment has been minimized.

Copy link

@sgotre sgotre commented May 8, 2018

Do you want to take over the original repo? https://github.com/sgotre/sphp-osx/blob/master/sphp i have no time to fix the bugs in there.

@csoseman

This comment has been minimized.

Copy link

@csoseman csoseman commented Dec 9, 2018

@rhukster would you be able to update your gist to include 7.3 as shown in the latest revision on my fork here: https://gist.github.com/csoseman/f53fc6dd70cf5a382b9fba7f84454961/revisions? 7.3 is now the default brew version for php. This script rocks so thanks for that!

@rhukster

This comment has been minimized.

Copy link
Owner Author

@rhukster rhukster commented Dec 12, 2018

I've now added 7.3 to this... thanks.

@rowild

This comment has been minimized.

Copy link

@rowild rowild commented Dec 14, 2018

Thank you for that script!
Not use, but I think or the native osx apache module, there should be a check against the mac osx version. High Sierra ships with v7 and therefore won't find a php5 module. Wouldn't that cause a problem?

Probably with a directory check?

$FILE = "\/usr\/libexec\/apache2\/libphp7.so

if [ -e $FILE  ]; 
then
  native_osx_php_apache_module="LoadModule php7_module libexec\/apache2\/libphp7.so"
else
  native_osx_php_apache_module="LoadModule php5_module libexec\/apache2\/libphp5.so"
fi
@maksim-pukh

This comment has been minimized.

Copy link

@maksim-pukh maksim-pukh commented Mar 3, 2019

Hi. I have an issue with homebrew: php links wrong, in services list "php" is written instead of "php@7.3".
Could you help me, please? The whole issue is on the homebrew forum

And I installed sphp from here

@gwvoigt

This comment has been minimized.

Copy link

@gwvoigt gwvoigt commented Mar 31, 2019

In my current httpd.conf I'm including a custom .conf file in which I load the php modules, so I had to modify the apache_conf_path to point to that file. Other than that it worked very well, thanks!

@signmeuptwice

This comment has been minimized.

Copy link

@signmeuptwice signmeuptwice commented May 15, 2019

Is it normal that I have to reboot for the change to be effective ? The script works without any error but if I php -v I still get the previous version until I reboot

@priesdelly

This comment has been minimized.

Copy link

@priesdelly priesdelly commented Oct 10, 2019

In your article (https://getgrav.org/blog/macos-catalina-apache-multiple-php-versions) httpd.conf is /usr/local/etc/httpd/httpd.conf

Why this file change "apache_conf_path" to "/etc/apache2/httpd.conf" ?

@thomasisberg

This comment has been minimized.

Copy link

@thomasisberg thomasisberg commented Feb 20, 2020

Hi! Works great! But I had to change this line:
sudo sed -i.bak "/$native_osx_php_apache_module/a\\
since Homebrew's Apache installed without a php module in the conf. (And if it did, it probably wouldn't be located at libexec/apache2/). Instead I used:
sudo sed -i.bak "/LoadModule rewrite_module lib\/httpd\/modules\/mod_rewrite.so/a\\

@Sinepel

This comment has been minimized.

Copy link

@Sinepel Sinepel commented Mar 7, 2020

Hi !

Am I the only one who has a problem with the icu4c library version when I switch from version 5.6/7.1 to 7.2/7.3/7.4 ?

5.6 and 7.1 works with icu4u 63.1 and 7.2, 7.3 and 7.4 with 64.2?

Thank you in advance !

@carlosescri

This comment has been minimized.

Copy link

@carlosescri carlosescri commented Apr 27, 2020

Hi!

FYI, I had problems with Apache restart, and solved them by changing the script to sudo apachectl -k restart (added -k).

@rhukster

This comment has been minimized.

Copy link
Owner Author

@rhukster rhukster commented May 6, 2020

I've updated the script to include the -k restart approach. I was having this myself and had updated locally, but not in the gist.

@vlad7code

This comment has been minimized.

Copy link

@vlad7code vlad7code commented May 14, 2020

Hi !

Am I the only one who has a problem with the icu4c library version when I switch from version 5.6/7.1 to 7.2/7.3/7.4 ?

5.6 and 7.1 works with icu4u 63.1 and 7.2, 7.3 and 7.4 with 64.2?

Thank you in advance !

Hi @Sinepel,
I have the same problem. Have you found out a solution for this?

Thank you!

@nick322

This comment has been minimized.

Copy link

@nick322 nick322 commented Jun 17, 2020

Hi @vlad7code ,@Sinepel,

You should upgrade icu4c , and rebuild php 5.6 and 7.1
see
eXolnet/homebrew-deprecated#23

check ICU version

php -i | grep ICU

Hi !
Am I the only one who has a problem with the icu4c library version when I switch from version 5.6/7.1 to 7.2/7.3/7.4 ?
5.6 and 7.1 works with icu4u 63.1 and 7.2, 7.3 and 7.4 with 64.2?
Thank you in advance !

Hi @Sinepel,
I have the same problem. Have you found out a solution for this?

Thank you!

@budjoe

This comment has been minimized.

Copy link

@budjoe budjoe commented Jun 17, 2020

Using this script on Catalina 10.15.5 with HOMEBREW_VERSION: 2.4.0
Had 2 issues -
Script does not stop the running php services
Script does not start the chosen php services
1 remaining issue -
if sudo login is still active, it does not restart Apache correctly, and no password entry required.
Works fine if sudo has timed out and password entry required.
--- Modified Script ---
#!/bin/bash

Creator: Phil Cook

Modified: Andy Miller

Modified Stephen Toth

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}))

brew_prefix=$(brew --prefix | sed 's#/#\/#g')

brew_array=("5.6","7.0","7.1","7.2","7.3","7.4")
php_array=("php@5.6" "php@7.0" "php@7.1" "php@7.2" "php@7.3" "php@7.4")
valet_support_php_version_array=("php@5.6" "php@7.0" "php@7.1" "php@7.2" "php@7.3" "php@7.4")
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"

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

php_module="$php5_module"
apache_php_lib_path="$apache_php5_lib_path"

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 " -s skip change of mod_php on apache"
echo " -s=* skip change of mod_php on apache or valet restart i.e (apache|valet,apache|valet)"
echo " -c=* switch a specific config (apache|valet,apache|valet"
echo
exit
fi

if [[ $(echo "$php_version" | sed 's/^php@//' | sed 's/.//') -ge 70 ]]; then
php_module="$php7_module"
apache_php_lib_path="$apache_php7_lib_path"
fi

apache_change=1
apache_conf_path="/usr/local/etc/httpd/httpd.conf"
apache_php_mod_path="$php_opt_path$php_version$apache_php_lib_path"

valet_restart=0

Check if valet is already install

hash valet 2>/dev/null && valet_installed=1 || valet_installed=0

POSITIONAL=()

Check for skip & change flag

while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
# This is a flag type option. Will catch either -s or --skip
-s|-s=|--skip=)
if [[ "${1#=}" == "-s" || "${1#=}" == "apache" ]]; then
apache_change=0
elif [ "${1#*=}" == "valet" ]; then
valet_restart=0
fi
;;

    # This is a flag type option. Will catch either -c or --change
    -c=*|--change=*)
         [[ "$1" == *"apache"* ]] && apache_change=1 || apache_change=0
         [[ "$1" == *"valet"* ]] && valet_restart=1 || valet_restart=0
    ;;

    *)
    POSITIONAL+=("$1") # save it in an array for later
    ;;
esac
# Shift after checking all the cases to get the next option
shift

done

What versions of php are installed via brew

for i in ${php_array[*]}; do
if [[ -n "$(brew ls --versions "$i")" ]]; then
php_installed_array+=("$i")
fi
done

Check if php version support via valet

if [[ (" ${valet_support_php_version_array[*]} " != "$php_version") && ($valet_restart -eq 1) ]]; then
echo "Sorry, but $php_version is not support via valet"
exit
fi

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

    # Stop valet service
    if [[ ($valet_installed -eq 1) && ($valet_restart -eq 1) ]]; then
        echo "Stop Valet service"
        valet stop
    fi

    # stop all running php services -- added
    echo "Stopping running php services"
    for i in ${php_installed_array[@]}; do
        brew services stop $i
    done

    # Switch Shell
    echo "Switching to $php_version"
    echo "Switching your shell"
    for i in ${php_installed_array[@]}; do
        brew unlink $i
    done
   # added --overwrite to ensure linked libraries are clean
    brew link --force --overwrite "$php_version"
    brew services start "$php_version"

    # Switch apache
    if [[ $apache_change -eq 1 ]]; then
        echo "You will need sudo power from now on"
        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"
            if [ $(echo "$j" | sed 's/^php@//' | sed 's/\.//') -ge 70 ]; then
                loop_php_module="$php7_module"
                loop_apache_php_lib_path="$apache_php7_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
                    sudo 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
                sudo sed -i.bak "/$native_osx_php_apache_module/a\\

$comment_apache_module_string\
" $apache_conf_path
fi
done
sudo 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"
sudo apachectl -k restart
fi

    # Switch valet
    if [[ $valet_restart -eq 1 ]]; then
        if [[ valet_installed -eq 1 ]]; then
            valet restart
         else
           echo "valet isn't installed in your system, will skip restarting valet service"
        fi
    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

@JanRogge

This comment has been minimized.

Copy link

@JanRogge JanRogge commented Nov 23, 2020

For PHP8 its not working for me because instead of php8_module now its just php_module .

@Bruno21

This comment has been minimized.

Copy link

@Bruno21 Bruno21 commented Dec 4, 2020

Work well, except when switching 7.x to 8.0: httpd.conf is well modified but php_info() stay at php 7.4. (it's ok for php cli).
Need to replace

           #brew services stop httpd
            #brew services start httpd
            sudo apachectl stop
            sleep 0.25
            sudo apachectl start
@Lombra

This comment has been minimized.

Copy link

@Lombra Lombra commented Jan 28, 2021

Hi,

I don't use macOS, but I was tasked with setting up an environment for someone on one of the new Apple Silicon MacBooks. (don't know if relevant)

I found that PHP was installed in /opt/homebrew/etc/php rather than /usr/local/etc/php, causing the script to fail. Modifying the script at line 58 to edit the search path accordingly seems to be enough, however.

@pixelninja

This comment has been minimized.

Copy link

@pixelninja pixelninja commented Feb 23, 2021

Hi,

I don't use macOS, but I was tasked with setting up an environment for someone on one of the new Apple Silicon MacBooks. (don't know if relevant)

I found that PHP was installed in /opt/homebrew/etc/php rather than /usr/local/etc/php, causing the script to fail. Modifying the script at line 58 to edit the search path accordingly seems to be enough, however.

Super useful @Lombra ! I was just about to post this.

Also note that I had to update line 52, which is the Apache config path to /opt/homebrew/etc/httpd/httpd.conf otherwise the switch doesn't update and reload Apache.

@rhukster

This comment has been minimized.

Copy link
Owner Author

@rhukster rhukster commented Feb 23, 2021

I really want to update this with automatic support for both intel + m1 paths. Not had a chance to look at this yet.

@rozsival

This comment has been minimized.

Copy link

@rozsival rozsival commented Mar 3, 2021

Awesome script! ❤️

I have created a lightweight version for those who use PHP-FPM as Brew service instead of mod_php in Apache. 🧑‍💻

Besides the fact FPM is preferred according to Apache Wiki, the major advantage of such approach is you don't have to restart Apache, nor modify its config files. You simply setup your PHP-FPM instances with the same basic configuration (meaning on the same port) and only choose which one should be running to handle PHP for Apache.

It also, of course, links correct Brew binaries.

Feel free to use it from here. 🚀

@sagarguhe

This comment has been minimized.

Copy link

@sagarguhe sagarguhe commented Apr 7, 2021

Work well, except when switching 7.x to 8.0: httpd.conf is well modified but php_info() stay at php 7.4. (it's ok for php cli).
Need to replace

           #brew services stop httpd
            #brew services start httpd
            sudo apachectl stop
            sleep 0.25
            sudo apachectl start

Yes same for me

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