Install multiple PHP versions and automatically switch versions for each directory
Tags: mac, ubuntu, php, phpenv
Published: 2022-11-17 01:33:14

---
title: Install multiple PHP versions and automatically switch versions for each directory
published: true
description: Install multiple PHP versions and automatically switch versions for each directory
tags: mac, ubuntu, php, phpenv
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2022-11-17 01:13 +0000
---


## Description
- Translated from [Qiita](https://qiita.com/yuki777/items/c8e33ca3290b55862c6a)
- I want to use multiple versions of PHP
- I want to automatically switch between different versions of PHP for each directory
- I don't want to do php builds because they are too difficult
- I want to support Mac and Ubuntu

## Install brew
- Install [Brew](https://brew.sh/)
- I thought brew was for macs only, but it can be installed on ubuntu too!

## Install php
- Install php
- Additional packages can be installed as needed, such as imagemagick
- In this article, **PHP is installed with brew. **
```bash
brew update
brew tap shivammathur/php
brew install php@8.1
brew install php@8.0
brew install php@7.4
brew install pkg-config
brew install imagemagick
```

## Install phpenv
- Install phpenv
- phpenv is used to switch between PHP versions using `phpenv global`, `phpenv local`, etc.
- In this article, **phpenv does not install PHP**.
```bash
# Install phpenv
curl -L https://raw.githubusercontent.com/phpenv/phpenv-installer/master/bin/phpenv-installer | bash

# Setup phpenv
$(cat << 'EOF' >> ~/.zshrc
# phpenv
export PHPENV_ROOT="$HOME/.phpenv"
if [ -d "${PHPENV_ROOT}" ]; then
  export PATH="${PHPENV_ROOT}/bin:${PATH}"
  eval "$(phpenv init -)"
fi
EOF
)

# restart shell
exec $SHELL -l
```


## Link each version of php installed by brew to ~/.phpenv/versions
- You need to link the php installed by brew so that phpenv can manage them. Manual work is tedious, so [I wrote a script.](https://gist.github.com/yuki777/6244823b8aa8cf4457e97e6407ada5ad/)
```bash
curl -fsSL https://gist.githubusercontent.com/yuki777/6244823b8aa8cf4457e97e6407ada5ad/raw/e988f8a1c112e4063768664104ba14d799e63782/link-phps.bash | bash
```

<details><summary>Source</summary><div>

```bash
#!/usr/bin/env bash

set -au

## Check cellar dir
cellarDir=$(brew --prefix)/Cellar
if [ ! -d "$cellarDir" ]; then
  echo "Not found. brew package path $cellarDir :("
  echo
  exit 1
fi

parentDirs=$(find $cellarDir/php* -type d -maxdepth 0)
echo "# Link the php installed by Brew to ~/.phpenv/versions"
for parentDir in $parentDirs
do
  childDirs=$(find "$parentDir"/* -type d -maxdepth 0)
  for childDir in $childDirs
  do
    phpPath=$childDir/bin/php
    if [ ! -f "$phpPath" ]; then
      continue
    fi
    major=$($phpPath -r 'echo PHP_MAJOR_VERSION;')
    minor=$($phpPath -r 'echo PHP_MINOR_VERSION;')
    patch=$($phpPath -r 'echo PHP_RELEASE_VERSION;')

    # unlink
    rm -f "$HOME"/.phpenv/versions/"$major"."$minor"
    rm -f "$HOME"/.phpenv/versions/"$major"."$minor"."$patch"

    # link
    linkCommand="ln -s $childDir $HOME/.phpenv/versions/$major.$minor"
    echo "$linkCommand"
    $linkCommand
    linkCommand="ln -s $childDir $HOME/.phpenv/versions/$major.$minor.$patch"
    echo "$linkCommand"
    $linkCommand
  done
done
```

</div></details>


## Tests
- Test that running `php -v` in global will use php 8.1
- Test that php 7.4 is automatically switched to php 7.4 when you move to the /tmp/php7.4
```bash
cd /tmp && mkdir php74 php80 php81

# set version
cd /tmp         && phpenv global 8.1 # set 8.1 as a global
cd /tmp/php74   && phpenv local  7.4 # pin 7.4 in this dir
cd /tmp/php80   && phpenv local  8.0 # pin 8.0 in this dir
cd /tmp/php81   && phpenv local  8.1 # pin 8.1 in this dir

# test version
cd /tmp         && php -v # => 8.1
cd /tmp/php74   && php -v # => 7.4
cd /tmp/php80   && php -v # => 8.0
cd /tmp/php81   && php -v # => 8.1
```

## Notes on brew upgrade
- When php is upgraded by brew upgrade, symlink will be broken, so you need to re-run the link.
```bash
curl -fsSL https://gist.githubusercontent.com/yuki777/6244823b8aa8cf4457e97e6407ada5ad/raw/e988f8a1c112e4063768664104ba14d799e63782/link-phps.bash | bash
```

## Summary
- Want to use multiple versions of PHP => with phpenv.
- Want to automatically switch between different versions of php for each directory => with phpenv.
- Don't want to waste time with php builds => install php with brew.
- I want to support Mac and Ubuntu => with brew and my own scripts.
- Special thanks, uzulla-san's [slide](https://speakerdeck.com/uzulla/phpfalsebirudonitukareta-falsede-phpenv-plus-homebrew?slide=11)

## and others
- About pecl installation
- This article is written assuming a clean installation, but there are cases where php, direnv, brew-php-switcher, etc. have already been installed.
- About specifying php version in vscode and phpstorm
- I will write more if there is demand for it.