DEV Community

Cover image for Manage Multiple Versions of PHP with Homebrew
Michael Mathews
Michael Mathews

Posted on

Manage Multiple Versions of PHP with Homebrew

Using Homebrew is a handy way to install multiple versions of PHP on MacOS. For example, to have both php 7.4 and 8.0 installed, use the brew install command.

First install the 7.4 version, like so:

% brew install php@7.4
Enter fullscreen mode Exit fullscreen mode

The syntax for specifying a specific version of a package with Homebrew is brew install <packageName>@<version>. In this case the package name is php and the version is 7.4 (defaulting to 7.4.32 as of this writing). If you leave off the @<version> part entirely, Homebrew will install whatever the latest version available is (8.1 as of this writing).

To check that version 7.4 of php is correctly installed:

% /opt/homebrew/opt/php@7.4/bin/php -v  
  PHP 7.4.32 (cli) (built: Sep 29 2022 10:45:51) ( NTS )
  Copyright (c) The PHP Group
  Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.32, Copyright (c), by Zend Technologies
Enter fullscreen mode Exit fullscreen mode

Ideally we would like to refer to /opt/homebrew/opt/php@7.4/bin/php simply as php on our command line. This requires another step:

% brew link --force --overwrite php@7.4
  Linking /opt/homebrew/Cellar/php@7.4/7.4.32... 812 symlinks created.

  If you need to have this software first in your PATH instead consider running:
  echo 'export PATH="/opt/homebrew/opt/php@7.4/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/opt/homebrew/opt/php@7.4/sbin:$PATH"' >> ~/.zshrc
Enter fullscreen mode Exit fullscreen mode

As a result of running brew link we can now find the linked version of php at this path: /opt/homebrew/bin/php.

% ls -l /opt/homebrew/bin/php
  lrwxr-xr-x  1 myuser  admin  32 15 Oct 18:34 /opt/homebrew/bin/php -> ../Cellar/php@7.4/7.4.32/bin/php
% /opt/homebrew/bin/php -v
  PHP 7.4.32 (cli) (built: Sep 29 2022 10:45:51) ( NTS )
  Copyright (c) The PHP Group
  Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.32, Copyright (c), by Zend Technologies
Enter fullscreen mode Exit fullscreen mode

The output of running brew link has a suggestion that we append two lines to the end of our ~/.zshrc file to tell our terminal that when we refer to php it should look for it first in the /opt/homebrew/opt/php@7.4/bin folder. You can do this but every time you brew link to a different version of php you will have to edit those lines. Instead I will take a slightly modified approach:

% echo 'export PATH="/opt/homebrew/sbin:/opt/homebrew/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc
Enter fullscreen mode Exit fullscreen mode

Now our terminal will find the linked version of php at /opt/homebrew/bin first whenever we refer to php.

% which php    
  /opt/homebrew/bin/php
% php -v
  PHP 7.4.32 (cli) (built: Sep 29 2022 10:45:51) ( NTS )
  Copyright (c) The PHP Group
  Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.32, Copyright (c), by Zend Technologies
Enter fullscreen mode Exit fullscreen mode

Now that we have php version 7.4 installed we can continue by installing php version 8.0 too.

% brew install php@8.0
Enter fullscreen mode Exit fullscreen mode

Now we tell brew to link to the new version of php:

% brew link --force --overwrite php@8.0
  Unlinking /opt/homebrew/Cellar/php@7.4/7.4.32... 328 symlinks removed.
  Linking /opt/homebrew/Cellar/php@8.0/8.0.24... 232 symlinks created.
Enter fullscreen mode Exit fullscreen mode

In the output from this command we again see the suggestion to run two commands containing the command export PATH... but due to the steps we took above, this won't be necessary.

% which php    
  /opt/homebrew/bin/php
% php -v
  PHP 8.0.24 (cli) (built: Sep 30 2022 08:39:20) ( NTS )
  Copyright (c) The PHP Group
  Zend Engine v4.0.24, Copyright (c) Zend Technologies
    with Xdebug v3.1.5, Copyright (c) 2002-2022, by Derick Rethans
    with Zend OPcache v8.0.24, Copyright (c), by Zend Technologies
Enter fullscreen mode Exit fullscreen mode

Now we can switch from versions of 7.4 to 8.0 by relinking from one to the other: brew link --force --overwrite php@7.4 or brew link --force --overwrite php@8.0 for example.

If you're not sure what versions are available to link to, try this command:

% brew ls --versions | grep '^php[ @]'
  php@7.4 7.4.32
  php@8.0 8.0.24
Enter fullscreen mode Exit fullscreen mode

Finally, below is the source code of a more full featured script that I call phpswitch. This script can be set to be executable and then run from the terminal like phpswitch 8.0 or phpswitch 7.4.

#!/bin/bash

if [ $# -ne 1 ]; then
    echo 1>&2 "USAGE: $0 <phpVersion>"
    exit 2
fi

INSTALLED_VERSIONS=`find /opt/homebrew/opt | grep 'php@' | sed 's/\/opt\/homebrew\/opt\/php@//'`

if [[ ! -f /opt/homebrew/opt/php@${1}/bin/php ]]; then
    echo 1>&2 "/opt/homebrew/opt/php@${1}/bin/php was not found"
    printf 'valid options:\n%s\n' "${INSTALLED_VERSIONS[*]}"
    exit 2
fi

for VERSION in ${INSTALLED_VERSIONS[*]}; do
    brew unlink php@$VERSION > /dev/null 2>&1
    brew services stop php@$VERSION > /dev/null 2>&1
done

brew link --force --overwrite php@$1 > /dev/null 2>&1
brew services start php@$1 > /dev/null 2>&1
Enter fullscreen mode Exit fullscreen mode

Top comments (5)

Collapse
 
vojtasvoboda profile image
Vojta Svoboda • Edited

I change PHP versions just with

brew unlink php@8.0
brew link php@7.4
Enter fullscreen mode Exit fullscreen mode

And it works without any script.

Collapse
 
robbertvancaem profile image
Robbert van Caem • Edited

I think you mean brew unlink php@8.0 and brew link php@7.4 🙂

Collapse
 
vojtasvoboda profile image
Vojta Svoboda

I've updated the comment, thanks.

Collapse
 
anoerak profile image
Seb

Hi,

Here is a small contribution to check version available on your system and pick one.
It also takes an optional argument if you want to switch directly to a version.

php-switch() {
    # List installed PHP versions
    INSTALLED_VERSIONS=$(find /opt/homebrew/opt | grep 'php@' | sed 's/\/opt\/homebrew\/opt\/php@//')

    # If no argument is provided, prompt availalbe version(s)
    if [ $# -eq 0 ]; then
        if [ -z "$INSTALLED_VERSIONS" ]; then
            echo "No PHP versions are installed."
            return 1
        fi

        echo "Available PHP version(s):"
        select VERSION in $INSTALLED_VERSIONS; do
            if [[ -n "$VERSION" ]]; then
                echo "You selected PHP $VERSION."
                break
            else
                echo "Invalid selection. Please choose a valid version."
            fi
        done
    else
        # Use the provided PHP version
        VERSION=$1
    fi

    # Check if the provided version exists
    if [[ ! -f /opt/homebrew/opt/php@${VERSION}/bin/php ]]; then
        echo 1>&2 "/opt/homebrew/opt/php@${VERSION}/bin/php was not found"
        echo "Valid options:"
        printf '%s\n' ${INSTALLED_VERSIONS[@]}
        return 2
    fi

    # Unlink and stop all other PHP versions
    for INSTALLED_VERSION in ${INSTALLED_VERSIONS[@]}; do
        brew unlink php@$INSTALLED_VERSION > /dev/null 2>&1
        brew services stop php@$INSTALLED_VERSION > /dev/null 2>&1
    done

    # Link and start the selected PHP version
    brew link --force --overwrite php@$VERSION > /dev/null 2>&1
    brew services start php@$VERSION > /dev/null 2>&1

    echo "Switched to PHP $VERSION."
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
leslieeeee profile image
Leslie

Have you tried ServBay.dev?
It's a much easier tool for PHP developers, providing a user-friendly experience, especially for beginners. It supports all versions of PHP, MariaDB, PostgreSQL, as well as Redis and Memcached. You can run multiple PHP instances simultaneously and switch between them effortlessly. It also offers easy updates without the need to configure environment variables. This tool has greatly simplified my PHP development and is definitely worth trying!