#!/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})) | |
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") | |
php_array=("php@5.6" "php@7.0" "php@7.1" "php@7.2" "php@7.3" "php@7.4" "php@8.0" "php@8.1") | |
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 |
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
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
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!
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
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" ?
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\\
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!
FYI, I had problems with Apache restart, and solved them by changing the script to sudo apachectl -k restart
(added -k
).
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.
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!
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!
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=
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
For PHP8 its not working for me because instead of php8_module
now its just php_module
.
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
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.
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.
I really want to update this with automatic support for both intel + m1 paths. Not had a chance to look at this yet.
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.
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
It might be better not to restrict the PHP version, and instead use Homebrew error codes to detect when a version isn't available. With the shivammathur/php
tap, at the time of writing this comment, there's php@8.1
and php@8.2
. And PHP is on a relatively fast release cycle with 8.1 planned to be released later this year (2021), and 8.2 planned for 2022.
Aside, just to point out the competition, there's this package available in the homebrew/core tap: brew-php-switcher
(lol, which is by Phil Cook
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
Same here i get really random results and i have to restart apache few times.. Anyone have any insights why is this happening, never happened before i migrate to m1?
In my case, it was the use of sudo when restarting HTTPD in SPHP. The OS boots HTTPD without sudo but then when using SPHP, sudo triggers a second instance. You can verify by executing:
brew services list
sudo brew services list
is switching to php8.1 available?
@adrian-kumu replace lines 12+13 from:
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")
TO:
brew_array=("5.6","7.0","7.1","7.2","7.3","7.4","8.0","8.1")
php_array=("php@5.6" "php@7.0" "php@7.1" "php@7.2" "php@7.3" "php@7.4" "php@8.0" "php@8.1")
Now the switch script is properly switching to php8.1
Updated for 8.1.
Not working for me on a freshly new install macos monterey, using a intel proc.
I installed php with brew install shivammathur/php/php@7.4
and when i use sphp i have the following error message :
Sorry, but php@7.3 is not installed via brew. Install by running: brew install php@7.3
@lchabrand, do you have PHP 7.3 installed because that's what it's complaining about. Also, checkout brew install brew-php-switcher
, however I'm not sure how up-to-date it is. It works with PHP 8.1.
$ brew info brew-php-switcher
brew-php-switcher: stable 2.4 (bottled), HEAD
Switch Apache / Valet / CLI configs between PHP versions
https://github.com/philcook/php-switcher
I run nginx rather than apache, and always prefer FPM, so this approach doesn't work generically enough to support that kind of config. As a result, I much prefer @rozsival's approach, and so i just posted a fork of his script that supports PHP 8.1 and drops old versions that are no longer supported.
Note that it's also possible to set up a redirect on the macOS firewall so that you don't have to run nginx/apache on a privileged port, and you can then have it run on its default port 8080, and the firewall forwards traffic from port 80. This is much more robust that reconfiguring the web server every time.
I've now added 7.3 to this... thanks.