phpbrewでバージョン管理する

# PHPもRubyみたいにバージョン管理したい
一番最初に触れた言語はPHPでその時は環境構築までやってちょっとチュートリアルやって挫折したと言う経験が昔ありました。で、その時はローカルに思いっきりPHPを落としてきて、色々ごちゃごちゃ設定したりしていたわけですが、Rubyを勉強して使うようになってからrbenvの存在を知り、バージョン管理するツールがあることを知ったので、PHPにもそう言うのないかと思ったら、phpbrewなるものがあることを教えてもらったので、インストールから、やっていきました。

物凄い使い方を理解するのに時間がかかりました。以下は、そのエラーや何やらの対処を書いてあります。結論からいきたい方は、使い方の結論から読んでください。

## phpbrewのインストール

公式のGitHubには、丁寧にインストール前に必要なものが指定されているので、こちらをまずやっていきます。
macOSでは2項目のみだったので、楽にできます。

[Requirement](https://github.com/phpbrew/phpbrew/wiki/Requirement)

```terminal
$ xcode-select --install
$ brew install autoconf pkg-config
```

次にBuilding development versions of PHPと言うことで、PHPを任意のソースツリーからビルドできるようにするには、追加の依存関係のセットが必要みたいなので、これもbrewでインストールしておきます。

```terminal
$ brew install bison re2c
```

ここまでが必要なパッケージのセットアップです。次は本体をダウンロードしてきます。
curlコマンドで落としてくると、

```terminal
$ curl -L -O https://github.com/phpbrew/phpbrew/releases/latest/download/phpbrew.phar
```

phpbrew.pharと言うファイルが落ちているので、chmodコマンドで実行権限を与えて、

```terminal
$ chmod +x phpbrew.phar
```

mvコマンドでバイナリディレクトリに移動させます。

```terminal
$ sudo mv phpbrew.phar /usr/local/bin/phpbrew
```

これでインストールは完了です。

## セットアップ

まずは初期化から始めます。下記コマンドを打つと、

```terminal
$ phpbrew init

Using root: /Users/naoya.ohsaki/.phpbrew
Initialization successfully finished!
<=====================================================>
Phpbrew environment is initialized, required directories are created under

    /Users/naoya.ohsaki/.phpbrew

Paste the following line(s) to the end of your ~/.bashrc and start a
new shell, phpbrew should be up and fully functional from there:

    source /Users/naoya.ohsaki/.phpbrew/bashrc

To enable PHP version info in your shell prompt, please set PHPBREW_SET_PROMPT=1
in your `~/.bashrc` before you source `~/.phpbrew/bashrc`

    export PHPBREW_SET_PROMPT=1

To enable .phpbrewrc file searching, please export the following variable:

    export PHPBREW_RC_ENABLE=1


For further instructions, simply run `phpbrew` to see the help message.

Enjoy phpbrew at $HOME!!

<=====================================================>
```

と出てくるので、

```.zshrc
$ source ~/.phpbrew/bashrc
```

を記述します。 初期化によって作成された.phpbrewディレクトリ内にあるbashrcファイルを読めるようにしています。


これで、下記のように、phpのバージョンを確認することができるようになっているはずです。

```terminal
$ phpbrew known

===> Fetching release list...
Downloading https://secure.php.net/releases/index.php?json&version=7&max=100 via curl extension
[==================================================================] 178.00/178.00B 100%
Redirecting to https://www.php.net/releases/index.php?json&version=7&max=100
Downloading https://secure.php.net/releases/index.php?json&version=5&max=100 via curl extension
[==================================================================] 178.00/178.00B 100%
Redirecting to https://www.php.net/releases/index.php?json&version=5&max=100
7.4: 7.4.5, 7.4.4, 7.4.3, 7.4.2, 7.4.1, 7.4.0 ...
7.3: 7.3.17, 7.3.16, 7.3.15, 7.3.14, 7.3.13, 7.3.12, 7.3.11, 7.3.10 ...
7.2: 7.2.30, 7.2.29, 7.2.28, 7.2.27, 7.2.26, 7.2.25, 7.2.24, 7.2.23 ...
7.1: 7.1.33, 7.1.32, 7.1.31, 7.1.30, 7.1.29, 7.1.28, 7.1.27, 7.1.26 ...
7.0: 7.0.33, 7.0.32, 7.0.31, 7.0.30, 7.0.29, 7.0.28, 7.0.27, 7.0.26 ...
5.6: 5.6.40, 5.6.39, 5.6.38, 5.6.37, 5.6.36, 5.6.35, 5.6.34, 5.6.33 ...
5.5: 5.5.38, 5.5.37, 5.5.36, 5.5.35, 5.5.34, 5.5.33, 5.5.32, 5.5.31 ...
5.4: 5.4.45, 5.4.44, 5.4.43, 5.4.42, 5.4.41, 5.4.40, 5.4.39, 5.4.38 ...
```

## バリアントとか言う概念

> PHPBrewはconfigureスクリプトのオプションをあなたの代わりに管理してくれます。 シンプルにバリアント名を指定してください。そうすると、PHPBrewがincludeパスとビルドオプションを検知してくれます。
PHPBrewはdefaultバリアントといくつかの「仮想バリアント」(Virtual variants)を提供します。 defaultバリアントは最もよく使われているバリアントを含んでいます。 仮想バリアントはいくつものバリアントのセットを定義するもので、ひとつの仮想バリアントを使用するだけで、一度に複数のバリアントを有効化します。
これらのバリアントに何が含まれているかを調べるには、variantsサブコマンドを実行して一覧を表示します。


だそうです。なんのこっちゃ分からんのですが、要するに、今までPHPをインストールする際に必要だったlibなんちゃらだの、mysql-pdoだの、mycriptだのを一緒に落としてくれる、つまり、PHP拡張モジュールの管理をしてくれると言うもののようです。基本的には、defaultと、使用するDBのバリアントを指定してPHPをビルドすれば良いようです。

下記コマンドを打つことで、利用可能なバリアントをみることができます。

```terminal
$ phpbrew variants

Variants:
  all, apxs2, bcmath, bz2, calendar, cgi, cli, ctype, curl, dba, debug, dom,
  dtrace, editline, embed, exif, fileinfo, filter, fpm, ftp, gcov, gd,
  gettext, gmp, hash, iconv, imap, inifile, inline, intl, ipc, ipv6, json,
  kerberos, ldap, libgcc, mbregex, mbstring, mcrypt, mhash, mysql, opcache,
  openssl, pcntl, pcre, pdo, pear, pgsql, phar, phpdbg, posix, readline,
  session, soap, sockets, sodium, sqlite, static, tidy, tokenizer, wddx,
  xml, xmlrpc, zip, zlib, zts


Virtual variants:
  dbs: sqlite, mysql, pgsql, pdo
  mb: mbstring, mbregex
  neutral:
  small: bz2, cli, dom, filter, ipc, json, mbregex, mbstring, pcre, phar,
  posix, readline, xml, curl, openssl
  default: bcmath, bz2, calendar, cli, ctype, dom, fileinfo, filter, ipc,
  json, mbregex, mbstring, mhash, pcntl, pcre, pdo, pear, phar, posix,
  readline, sockets, tokenizer, xml, curl, openssl, zip
  everything: dba, ipv6, dom, calendar, wddx, static, inifile, inline, cli,
  ftp, filter, gcov, zts, json, hash, exif, mbstring, mbregex, libgcc,
  pdo, posix, embed, sockets, debug, phpdbg, zip, bcmath, fileinfo, ctype,
  cgi, soap, pcntl, phar, session, tokenizer, opcache, imap, ldap, tidy,
  kerberos, xmlrpc, fpm, dtrace, pcre, mhash, mcrypt, zlib, curl, readline,
  editline, gd, intl, sodium, openssl, mysql, sqlite, pgsql, xml, gettext,
  iconv, bz2, ipc, gmp, pear


Using variants to build PHP:

  phpbrew install php-5.3.10 +default
  phpbrew install php-5.3.10 +mysql +pdo
  phpbrew install php-5.3.10 +mysql +pdo +apxs2
  phpbrew install php-5.3.10 +mysql +pdo +apxs2=/usr/bin/apxs2
```

##### バリアントだけを追加でインストールする

```terminal
$ phpbrew install ext バリアント名
```

## phpをビルドしてみる
今回は、自分が環境構築することを目的とした開発プロダクトを例にビルドをしています。

```terminal
$ phpbrew install 5.6 +pgsql +pdo
```

最初、これを打ってみると、エラーが出た。

```terminal
$ Error: Configure failed:
The last 5 lines in the log file:
checking Oracle OCI support for PDO... no

checking for ODBC v3 support for PDO... no

checking for PostgreSQL support for PDO... yes

checking for pg_config... not found

configure: error: Cannot find libpq-fe.h. Please specify correct PostgreSQL installation path

Please checkout the build log file for more details:
	 tail /Users/naoya.ohsaki/.phpbrew/build/php-5.6.40/build.log
```

なんだか、libpq-fe.hと言うのが見つからないようです。バリアントは補完してくれないのかよ！と思いながら、散々調べて時間を食ったのですが、最終的に結論はインストールの手順にあったようです。本体は別途、homebrewで入れないといけないんですね。本体があればそれに関係する拡張モジュールをインストールできるということなんでしょうね、恐らく。

```terminal
$ brew install postgeresql
```

まず最初にpostgresqlをインストールします。で、その後に下記を打ったら、うまくいきました。ビルドには数分かかります。

```terminal
$ phpbrew install 5.6 +pgsql +pdo
===> phpbrew will now build 5.6.40
===> Loading and resolving variants...
Homebrew prefix "/usr/local/Cellar/libxml2/2.9.10_1" does not exist.
Checking distribution checksum...
Checksum matched: ffd025d34623553ab2f7fd8fb21d0c9e6f9fa30dc565ca03a1d7b763023fba00
===> Distribution file was successfully extracted, skipping...
===> Checking patches...
Checking patch for replace apache php module name with custom version name
Checking patch for replace freetype-config with pkg-config on php older than 7.4
Found existing build.log, renaming it to /Users/naoya.ohsaki/.phpbrew/build/php-5.6.40/build.log.1587952542
===> Configuring 5.6.40...


Use tail command to see what's going on:
   $ tail -F '/Users/naoya.ohsaki/.phpbrew/build/php-5.6.40/build.log'


===> Checking patches...
Checking patch for php5.3.29 multi-sapi
Checking patch for php5.3.x on 64bit machine when intl is enabled.
Checking patch for openssl dso linking patch
Checking patch for php5.6 with openssl 1.1.x patch.
===> Building...
Build finished: 4.1 minutes.
Installing...
---> Creating php-fpm.conf
---> Creating php.ini
---> Copying /Users/naoya.ohsaki/.phpbrew/build/php-5.6.40/php.ini-development
---> Found date.timezone is not set, patching...
Congratulations! Now you have PHP with 5.6.40 as php-5.6.40

* To configure your installed PHP further, you can edit the config file at
    /Users/naoya.ohsaki/.phpbrew/php/php-5.6.40/etc/php.ini

To use the newly built PHP, try the line(s) below:

    $ phpbrew use php-5.6.40

Or you can use switch command to switch your default php to php-5.6.40:

    $ phpbrew switch php-5.6.40

Enjoy!
```

下記コマンドを打つと、今の指定されているPHPのバージョンが表示されます。無事インストールできているようですね。

```terminal
$ phpbrew list
* (system)
  php-5.6.40
```

## バージョン切り替えと終了

```terminal
use (一時的なバージョンの切り替え)
$ phpbrew use php-5.6.40

switch (デフォルトで使用するバージョンを切り替える)
$ phpbrew switch php-5.6.40

phpbrewを使用するのをやめる
$ phpbrew off
```

## 警告やら、エラーの対処まとめ
先のようにインストールしたは良いのですが、その直後にphpbrewが壊れました。
bzip2が無いと、ぶっ壊れるようです。どんなphpbrewのコマンドを打っても、下記のような文句を吐いてくるようになる。

```terminal
PHP Fatal error:  Uncaught exception 'PharException' with message 'bz2 extension is required for bzip2 compressed .phar file "/usr/local/bin/phpbrew"' in /usr/local/bin/phpbrew:10
Stack trace:
#0 /usr/local/bin/phpbrew(10): Phar::mapPhar('box-auto-genera...')
#1 {main}
  thrown in /usr/local/bin/phpbrew on line 10

Fatal error: Uncaught exception 'PharException' with message 'bz2 extension is required for bzip2 compressed .phar file "/usr/local/bin/phpbrew"' in /usr/local/bin/phpbrew:10
Stack trace:
#0 /usr/local/bin/phpbrew(10): Phar::mapPhar('box-auto-genera...')
#1 {main}
  thrown in /usr/local/bin/phpbrew on line 10
```

だから、bzip2をbrewでインストールし、参照先をbrewでインストールしたbzip２先を指定する。

```terminal
$ brew install bzip2
```

```terminal
$ phpbrew install 5.6 +b2="$(brew --prefix bzip2)"
```

WARNINGが出るようになったから、extを使って特定の足りてないバリアントだけを突っ込んでやれば良い。

```terminal
$ phpbrew list

# WARNING: json extension is required for parsing release info.
# WARNING: ctype extension might be required for parsing yaml file.
* php-5.6.40
```

```terminal
$ phpbrew ext install json
$ phpbrew ext install ctype
```

使い方を理解するのにかなり時間を取らされました・・・全くもって鬱陶しい・・・

# 使い方の結論
順番としては三段階であると思っています。セットアップ、phpインストール、バリアントのインストールです。

セットアップ

```terminal
$ brew install autoconf pkg-config

$ brew install bison re2c bzip2

$ curl -L -O https://github.com/phpbrew/phpbrew/releases/latest/download/phpbrew.phar

$ chmod +x phpbrew.phar

$ sudo mv phpbrew.phar /usr/local/bin/phpbrew

$ source ~/.phpbrew/bashrc
```

使うphpをバージョン指定してインストールする際にbzip2の参照先を指定

```terminal
$ phpbrew install 5.6 +b2="$(brew --prefix bzip2)"
```

必要なバリアントや、警告やエラーで要求されているバリアントを個別に入れる。

```terminal
$ phpbrew ext install pgsql
```