複数のPHPバージョンをインストールし、ディレクトリごとに自動でバージョンを切り替える

# UPDATE
- [miseを使って複数のPHPバージョンをインストールする ](https://qiita.com/yuki777/items/8c71f4535e696a2434b3)を書きました。

# 概要
- 複数バージョンのPHPを使いたい
- ディレクトリごとに別バージョンのPHPを自動で切り替えたい
- phpビルドは難しい!!のでやりたくない
- MacとUbuntuに対応したい

# Install brew
- [Brew](https://brew.sh/)をインストールします
- brewはmac専用だと思っていましたが、ubuntuにもインストールできるんですね

# Install php
- phpをインストールします
- imagemagickなど必要に合わせて追加のパッケージをインストールします
- 本記事では**PHPのインストールは下記の通り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
- [phpenv](https://github.com/phpenv/phpenv-installer)をインストールします
- phpenvは`phpenv global`や`phpenv local`などを使って、PHPバージョンの切り替えに使用します
- 本記事では**phpenvではPHPのインストールを行いません**
- 普通にinstallしますが、zshなら下記の通りです。
```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
)

# shell再起動
exec $SHELL -l
```


# Brewでインストールした各バージョンのphpを ~/.phpenv/versions にlinkする
- phpenvが `~/.phpenv/versions` をバージョン管理のディレクトリとして使用します
- brewでインストールしたphpをphpenvが管理できるようにリンクする必要がありますが手動は面倒ですので [スクリプト](https://gist.github.com/yuki777/6244823b8aa8cf4457e97e6407ada5ad)を書きました
```bash
curl -fsSL https://gist.githubusercontent.com/yuki777/6244823b8aa8cf4457e97e6407ada5ad/raw/e988f8a1c112e4063768664104ba14d799e63782/link-phps.bash | bash
```

<details><summary>ソース</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>


# 動作確認
- ふつうに`php -v`を実行するとphp 8.1が使われることをテストします
- php7.4を使いたいディレクトリに移動すると自動的にphp 7.4に切り替わることなどをテストします
```bash
cd /tmp && mkdir php74 php80 php81

# set version
cd /tmp         && phpenv global 8.1 # globalなphpは8.1にする
cd /tmp/php74   && phpenv local  7.4 # このディレクトリは7.4にする
cd /tmp/php80   && phpenv local  8.0 # このディレクトリは8.0にする
cd /tmp/php81   && phpenv local  8.1 # このディレクトリは8.1にする

# 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
```

# brew upgrade時の注意点
- brew upgradeによりphpがバージョンアップするとsymlinkが切れるため、linkを再実行する必要があります
```bash
# さきほどと同じコマンドです
curl -fsSL https://gist.githubusercontent.com/yuki777/6244823b8aa8cf4457e97e6407ada5ad/raw/e988f8a1c112e4063768664104ba14d799e63782/link-phps.bash | bash
```

# まとめ
- 複数バージョンのPHPを使いたい => phpenvで。
- ディレクトリごとに別バージョンのPHPを自動で切り替えたい => phpenvで。
- phpビルドで時間を無駄にしたくない => brewでphpをインストールする。
- MacとUbuntuに対応したい => brewと自作のスクリプトで。
- @uzulla さんの[スライド](https://speakerdeck.com/uzulla/phpfalsebirudonitukareta-falsede-phpenv-plus-homebrew?slide=11) に感謝です。

# ほか
- peclインストールについて
- 本記事ではまっさらな状態を想定して書きましたが、すでにインストール済みのphpやdirenvやbrew-php-switcherなどがあるケースについて
- vscodeやphpstormでのphpバージョン指定について
- など需要があれば書きます