Switch between any installed php version in MAMP

By default, the MAMP’s free UI only lets you choose between php 5.3 and 5.4.
Developing and patching on hosting platforms that don’t or can’t install the latest version as soon as its available makes it useful to be able to choose *any* of the php versions MAMP makes available.

I could’ve just paid for MAMP Pro, but the pleasure of scripting it myself and revising sed and awk in the process couldn’t be missed.

First, awk the currently active php version from MAMP’s httpd.conf – splitting the matched line with a “/” delimiter:

awk -F '/'

then extracting the 6th “chunk”:

{ print $6 }

Then list the php version directories in the MAMP folder, using sed to erase the bits of the wide directory listing we don’t need, finally sorting the result in proper version order:

versionlist=`ls -d /Applications/MAMP/bin/php/php5.* | sed 's/\/Applications\/MAMP\/bin\/php\///g' | sort -t. -k 1,1n -k 2,2n -k 3,3n`

Full listing:

#!/bin/bash

# Get current php version
currentphp=`awk -F '/' '/LoadModule php5_module/ { print $6 }' /Applications/MAMP/conf/apache/httpd.conf`
 
# include the CocoaDialog app for Platypus' benefit.
CD="CocoaDialog.app/Contents/MacOS/CocoaDialog"
 
# Get the list of currently installed php versions in the MAMP hierarchy.
versionlist=`ls -d /Applications/MAMP/bin/php/php5.* | sed 's/\/Applications\/MAMP\/bin\/php\///g' | sort -t. -k 1,1n -k 2,2n -k 3,3n`
 
# Create the drop-down menu.
rv=`$CD dropdown --string-output  --text "The drop-down lists all php versions on this system. $currentphp is active. Which do you want to enable?" --items $versionlist --button1 "Ok"` 
 
# extract the version number from the drop-down result
chosen=`echo $rv | awk -F' ' '{ print $2 }'`
 
# Replace the decimal points with slashes
fixed=`echo $chosen | sed 's/\./\\\./g'` 
 
# Overwrite httpd.conf's existing php version with the new, chosen one.
sed -i 'BAK' -E "s/php5\.[0-9]{1,}\.[0-9]{1,}/$fixed/" /Applications/MAMP/conf/apache/httpd.conf
 
# Restart apache *gracefully*
/Applications/MAMP/bin/apache2/bin/apachectl graceful
 
# Re-check the current php version in httpd.conf *just in case*   
newphp=`awk -F '/' '/LoadModule php5_module/ { print $6 }' /Applications/MAMP/conf/apache/httpd.conf`
 
# ...and tell the user what the current version is. 
$CD ok-msgbox --no-cancel --text "$newphp is now enabled."

Bundling it into a simple [cmd][space] app with Platypus was as easy as including the CocoaDialog package and adding a few messages:

Screen shot 2013-06-11 at 17.25.16

Used in combination with my command line php version selector, I can test against any of 8 different php versions with minimum effort.

Execute scripts with different versions of php

There are several versions of php in my MAMP installation. I’ve built a script (appified with Platypus) that switches between them on the fly, but no elegant way to switch between them in a shell without *typing* redundantly.

So here’s a script to execute a standard .php file on the command line using any version of php on the system; actually any version just here:

/Applications/MAMP/bin/php/php5.*

Sample usage:

./phpVersionsExec -sv 3.2 -f factory_methods.php

The script accepts partial command line parameters, or runs interactively, or both if your command line is a little flaky. It tries to use sane defaults (reading the current php version from httpd.conf) and allows you to a useful combination of test file and php version… and at that point I stopped scripting before I’d reengineered Wheel v.1.0.

#!/bin/bash

# Functions are defined

usage(){
    echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
    echo "* Usage:"
    echo "$0 [-f lf | filename.php] [-v {sv | hc | php{ n | n.n | n.n.n} }] | [-i] "
    echo "*"
    echo " -i                        - interactive mode."
    echo " -s                        - store php version and filename as defaults."
    echo " -f filename.php           - use filename.php"
    echo " -f lsd                    - use last-stored default filename."
    echo " -v lsd                    - use last-stored default php version."
    echo " -v chc                    - use current httpd.conf php version."
    echo " -v p -f index.php         - use highest version of php on the system."
    echo " -v 5 -f index.php      - use highest version of php 5."
    echo " -v 5.3 -f index.php    - use highest version of php 5.3 if available."
    echo " -v 5.3.20 -f index.php - use php 5.3.20 if available."
    echo "*"
    echo "* The script stores its 'default' php version (-v sd) and last file used (-f lf) in ~/.phpVersionExec.ini."
    echo "*"
    exit 1
}
 
initialiseDefaults() {
    # Set store-in-ini-file flag to false 
    storeDefaults=
 
    # Set goInteractive flag to false 
    goInteractive=
 
    # Set found-your-php-version flag to false 
    phpVersionExists=
 
    # Read all versions of php in MAMP folder hierarchy.
    installedPhpVersions=`ls -d /Applications/MAMP/bin/php/php5.* | sed 's/\/Applications\/MAMP\/bin\/php\///g' | sort -t. -k 1,1rn -k 2,2rn -k 3,3rn`
 
    # Read defaults from ini file if present.
    if [ -f ~/.phpVersionExec.ini ]; then
	a=0
	while read line
	do a=$(($a+1));
	    case "$a" in
		1) iniPhpVersion=$line;;
		2) iniPhpFile=$line;;
	    esac;
	done < ~/.phpVersionExec.ini
    fi
 
    # Read current MAMP default php version from httpd.conf  
    httpdConfPhpVersion=`awk -F '/' '/LoadModule php5_module/ { print $6 }' /Applications/MAMP/conf/apache/httpd.conf`
}
 
storeTheDefaults() {
    # Store last exec'd phpVersion and phpFile
    echo "Storing defaults:" 		    
    echo "$execPhpVersion" > ~/.phpVersionExec.ini
    echo "$phpFile" >> ~/.phpVersionExec.ini
    cat ~/.phpVersionExec.ini
}
 
execPhp () {
		echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
		echo "* Chosen php version is $execPhpVersion"
		echo "*"
		echo "* Running command: /Applications/MAMP/bin/php/$execPhpVersion/bin/php -d display_errors=On -c /Applications/MAMP/bin/php/$execPhpVersion/conf/ -f $phpFile"
		echo "*"
		echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
		echo "* PHP output begins:"
		echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
		/Applications/MAMP/bin/php/$execPhpVersion/bin/php -d display_errors=On -c /Applications/MAMP/bin/php/$execPhpVersion/conf/ -f $phpFile
		echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
		echo "* PHP output ends."
		echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
		if [[ $storeDefaults ]] ; then
		    storeTheDefaults
		fi
		exit 0
}
 
main() {
        # Use the last-stored-default php version or current Httpd.conf php version
	case $phpVersion in
	    lsd) phpVersion=$iniPhpVersion;;
	    chc) phpVersion=$httpdConfPhpVersion;;
	esac
 
        # Use the last-stored-default filename
	if [ $phpFile = "lsd" ]; then
	    phpFile=$iniPhpFile
	fi
 
        # Make sure the file exists - if not, go interactive.
	if [ ! -f $phpFile ]; then
	    	echo "The file selected - $phpFile - doesn't exist."
		interactive
	fi;
 
        # If the finally selected phpVersion is one of those currently in the MAMP stack... use it.
	for z in $installedPhpVersions; 
	do 
		if grep --quiet $phpVersion <<< $z; then
			execPhpVersion=$z
			phpVersionExists=true
			execPhp
		fi;
	done
 
        # If the finally selected phpVersion ISN'T one of those currently in the MAMP stack... get interactive.
	if [[ ! $phpVersionExists ]]; then
	    echo "Couldn't parse $phpVersion as an installed php version."   
	    interactive
	fi
}
 
interactive() {
	echo "Enter as accurate a php version as you need:"
        if [ ${#phpVersion} -gt 0 ]; then
	    echo " - ENTER for already-entered $phpVersion"
	    echo " - chc for httpd.conf php version: $httpdConfPhpVersion"
	else
	    echo " - ENTER for httpd.conf php version: $httpdConfPhpVersion"
	    phpVersion=$httpdConfPhpVersion
	fi
	echo " - lsd for Last Stored Default: $iniPhpVersion"
	echo " - N, N.N or N.N.N to select an installed php version:"
	echo "$installedPhpVersions"
	read interactivePhpVersion
	if [ ${#interactivePhpVersion} -gt 0 ]; then
	    phpVersion=$interactivePhpVersion
	else
	    echo "Defaulting to: $phpVersion"
	fi
 
	echo "Enter the php file you want to execute:"
	if [ ${#phpFile} -gt 0 ]; then
	    echo " - ENTER for already-entered $phpFile"
	    echo " - lsd for Last Stored Default: $iniPhpFile"
	else
	    echo " - ENTER for Last Stored Default: $iniPhpFile"
	    phpFile=$iniPhpFile
	fi
	read interactivePhpFile
	if [ ${#interactivePhpFile} -gt 0 ]; then
	    phpFile=$interactivePhpFile
	else
	    echo "Defaulting to $phpFile"
	fi
 
	main
}
 
# BEGIN 

initialiseDefaults
 
# Check and store any given options.
while getopts "sihv:f:" opt
do
        case "$opt" in
        v) phpVersion=$OPTARG;;
        f) phpFile=$OPTARG;;
        h) usage;;
        \?) usage;;
	s) storeDefaults=true;;
	i) goInteractive=true;;
        esac
done
 
 
# If goInteractive is true, go straight to interactive mode.
if [ $goInteractive ] ; then
        interactive
fi
 
# If exactly four arguments are given, go straight to main() initally bypassing the interactive mode.
if [ $# -eq 4 ] ; then
        main
fi
 
# If a strange number of arguments are given, display the help.
usage