Switching PHP versions when using Homebrew

Homebrew is an excellent option for installing one or more PHP versions on your Mac.

But how can you switch PHP versions when you have installed more than one version of PHP with Homebrew?

Which do you prefer - slowly or quickly?

Scenario

You have installed PHP 7.4, 8.0, 8.1, and 8.2 with Homebrew. You have no idea which PHP version is currently linked, but you want to use PHP 8.2.

Slowly switching PHP versions

First, you need to find out which PHP version is currently linked.

Running

php -v

yields

PHP 7.4.33 (cli) (built: Jan 21 2023 06:43:54) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.33, Copyright (c), by Zend Technologies

Second, since you know that PHP 7.4 is currently linked, you need to unlink PHP 7.4.

Running

brew unlink php@7.4

yields

Unlinking /opt/homebrew/Cellar/php@7.4/7.4.33_1... 25 symlinks removed.

Third, you need to link PHP 8.2, the PHP version you want to use.

Running

brew link php@8.2 --force --overwrite

yields

Linking /opt/homebrew/Cellar/php/8.2.1_1... 24 symlinks created.

Fourth, you want to double-check that PHP 8.2 is actually linked now.

Running

php -v

yields

PHP 8.2.1 (cli) (built: Jan 12 2023 03:48:24) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.1, Copyright (c), by Zend Technologies

Perfect, you can start working with PHP 8.2 after running four (!) commands.

Quickly switching PHP versions

How about running a single command instead of four commands?

How about running

8.2

to switch from any (!) PHP version to PHP 8.2? Let me show you how you can achieve that in two steps.

First, you need to install a modern version of grep with Homebrew.

Running

grep --version

on macOS Ventura yields

grep (BSD grep, GNU compatible) 2.6.0-FreeBSD

Unfortunately, that version does not support Perl-compatible regular expressions (PCREs) that you will use in the next step.

Running

brew install grep

yields

==> Fetching grep
==> Downloading https://ghcr.io/v2/homebrew/core/grep/manifests/3.8_1
Already downloaded: /Users/am/Library/Caches/Homebrew/downloads/a2ee255269e00fca81c021b40c338155577736b42bab878651de2922798bd235--grep-3.8_1.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/grep/blobs/sha256:d2450448352fb2c389634cab3dec581882f6fc0f02a79489b4ba9c603b8f780b
Already downloaded: /Users/am/Library/Caches/Homebrew/downloads/aefda17db919b6aed862b1ae9d2deb2d07197fef50b34f0bcacf179108b8fd12--grep--3.8_1.arm64_ventura.bottle.tar.gz
==> Pouring grep--3.8_1.arm64_ventura.bottle.tar.gz
==> Caveats
All commands have been installed with the prefix "g".
If you need to use these commands with their normal names, you
can add a "gnubin" directory to your PATH from your bashrc like:
  PATH="/opt/homebrew/opt/grep/libexec/gnubin:$PATH"
==> Summary
🍺  /opt/homebrew/Cellar/grep/3.8_1: 19 files, 1MB
==> Running `brew cleanup grep`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

💡 Note that the command grep has been installed with the prefix g to allow you to use grep as installed with macOS if necessary.

Second, after careful inspection, add the following shell script to ~/.zshrc.

# determine versions of PHP installed with HomeBrew
installedPhpVersions=($(brew ls --versions | ggrep -E 'php(@.*)?\s' | ggrep -oP '(?<=\s)\d\.\d' | uniq | sort))

# create alias for every version of PHP installed with HomeBrew
for phpVersion in ${installedPhpVersions[*]}; do
    value="{"

    for otherPhpVersion in ${installedPhpVersions[*]}; do
        if [ "${otherPhpVersion}" = "${phpVersion}" ]; then
            continue;
        fi

        value="${value} brew unlink php@${otherPhpVersion};"
    done

    value="${value} brew link php@${phpVersion} --force --overwrite; } &> /dev/null && php -v"

    alias "${phpVersion}"="${value}"
done

The script will first determine the versions of PHP you have installed with Homebrew.

The script will then create aliases for each PHP version you have installed with Homebrew. For each PHP version, the corresponding alias will unlink all other PHP versions, link the PHP version, and finally show the version information.

By adding the script to .zshrc, the script will run every time you open a new terminal. This means that the list of aliases will stay current at all times, depending on the versions of PHP that you have currently installed with Homebrew.

When you have PHP 7.4, 8.0, 8.1, and 8.2 installed with Homebrew, added the script to .zshrc, and opened a new terminal, running

alias | grep php

yields

7.4='{ brew unlink php@8.0; brew unlink php@8.1; brew unlink php@8.2; brew link php@7.4 --force --overwrite; } &> /dev/null && php -v'
8.0='{ brew unlink php@7.4; brew unlink php@8.1; brew unlink php@8.2; brew link php@8.0 --force --overwrite; } &> /dev/null && php -v'
8.1='{ brew unlink php@7.4; brew unlink php@8.0; brew unlink php@8.2; brew link php@8.1 --force --overwrite; } &> /dev/null && php -v'
8.2='{ brew unlink php@7.4; brew unlink php@8.0; brew unlink php@8.1; brew link php@8.2 --force --overwrite; } &> /dev/null && php -v'

As promised, Running

8.2

switches to PHP 8.2 and yields

PHP 8.2.1 (cli) (built: Jan 12 2023 03:48:24) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.1, Copyright (c), by Zend Technologies

Have you found a better option for switching PHP versions when using Homebrew?

Do you find this article helpful?

Do you have feedback?

Do you need help with your PHP project?