phpenvで複数バージョンのPHPをディレクトリ毎に設定する



開発をする上で、複数のPHPバージョンが必要な場合がありますね。そんなときに、Rubyのrbenv、Pythonのpyenvのように、複数のバージョンのPHPを管理するツールとして、PHPにもphpenvがあります。そのインストール方法と簡単なphpenvの利用方法をメモ。
**phpenv**で全体と各ディレクトリ毎のPHPのバージョンを管理し、 **php-build**というツールでphpenvでインストールするPHPをビルドします。

# 前提環境

* Mac OS X Yosemite (10.10.9)
* Homebrewがインストールされていること

## インストール

インストールは基本的に`homebrew`を利用する。

### phpenvをインストール

~~`$ brew install phpenv`~~

→　2015/12/09の時点でうまくいかなくなっていた。

以下の方法に切り替え

`curl -L https://raw.github.com/CHH/phpenv/master/bin/phpenv-install.sh | bash`

### .bashrcに設定を記述する

phpenvインストール時に表示されているように設定を記述する。

```
$ vim ~/.bashrc

# For PHP Environment
export PHP_ROOT="${HOME}/.phpenv"
if [ -d "${PHP_ROOT}" ]; then
   export PATH=${PHP_ROOT}/bin:$PATH
   eval $(phpenv init -)
fi
```

ここまでやったら、いちど`.bashrc`を再読み込み。

`$ . ~/.bashrc`

### php-buildをインストールする

**php-build**は複数のバージョンのPHP環境をインストールするためのツール。phpenvは ~/.phpenvにインストールされているとして`git clone`する。

```
$ git clone git://github.com/CHH/php-build.git $HOME/.phpenv/plugins/php-build

plugins/php-build
Cloning into '/Users/hogehoge/.phpenv/plugins/php-build'...
remote: Counting objects: 2743, done.
remote: Total 2743 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2743/2743), 401.96 KiB | 326.00 KiB/s, done.
Resolving deltas: 100% (1482/1482), done.
Checking connectivity... done.
```
 
### インストール可能なPHPバージョンを表示してみる。

以下のコマンドを実行すると利用可能なバージョンがずらっと表示されるので、あとは好きなバージョンを選択してインストールするだけ。。(実際はつまずくポイントがある。)

```
$ phpenv install -l

usage: phpenv install VERSION

Available versions:
 5.2.17
 5.3.10
 5.3.11
 5.3.12
 5.3.13
 5.3.14
 5.3.15
...
 5.6.4
 master
```

### PHPをインストールするときに必要なライブラリをインストールする

php-buildを利用して、必要なバージョンのPHPをビルドする際に必要となるライブラリを事前にインストールする。

* 必要となるパッケージ
    * libevent
    * libjpeg
    * libpng
    * mcrypt
    * libtool
    * openssl
    * autoconf
    * libxml2
    * lemon
    * re2c

```
$ brew install <パッケージ>
```

PHPのインストールの際にopensslのインストールパスが必要となるので、以下に記述。

```
$ brew install openssl
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/openssl-1.0.1j_1.yosemite.bottle.tar.gz
...

==> Summary
?  /usr/local/Cellar/openssl/1.0.1j_1: 431 files, 15M
```

### libxmlにパッチをあてる。

**phpenv**コマンドを使って、PHPをインストールする際以下のようなエラーがでる。

```
こんなエラー。
var/tmp/php-build/source/5.3.3/ext/dom/node.c:1950:8: warning: assigning to 'char *' from 'xmlChar *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        value = xmlGetNodePath(nodep);
              ^ ~~~~~~~~~~~~~~~~~~~~~
22 warnings and 2 errors generated.
make: *** [ext/dom/node.lo] Error 1
```

どうやら、libxmlの問題らしいので、パッチをあてる。

パッチを取得する。

```
$ cd /tmp
$ curl -O https://mail.gnome.org/archives/xml/2012-August/txtbgxGXAvz4N.txt
$ mv /tmp/txtbgxGXAvz4N.txt /tmp/php-patch.txt
```

パッチをあてる。

```
$ cd /var/tmp/php-build/source/5.3.3
$ patch -p0 < /tmp/php-patch.txt
patching file ext/dom/node.c
Hunk #1 succeeded at 1900 (offset 5 lines).
patching file ext/dom/documenttype.c
patching file ext/simplexml/simplexml.c
Hunk #1 succeeded at 1385 (offset -32 lines).
```

◆参照 http://d.hatena.ne.jp/oppara/20140106/p1


ここまで、事前に必要となるパッケージが整ったので **phpenv**コマンドを使ったPHPのビルドを実行してみる。PHPのインストールには以下のようなコマンドを用いる。

    $ phpenv install <PHPバージョン>

実際にphpenvコマンドを利用してPHPをビルドすると以下のように表示される。

```
$ CONFIGURE_OPTS="--with-openssl=<pathtoopenssl>" phpenv install 5.3.3
[Info]: Loaded apc Plugin.
[Info]: Loaded composer Plugin.
[Info]: Loaded pyrus Plugin.
[Info]: Loaded xdebug Plugin.
[Info]: Loaded xhprof Plugin.
[Info]: php.ini-production gets used as php.ini
[Info]: Building 5.3.3 into /Users/<hogehoge>/.phpenv/versions/5.3.3
[Skipping]: Already downloaded and extracted http://git.php.net/?p=web/php-distributions.git;a=blob;f=php-5.3.3.tar.bz2;h=c473d92b8399ed7dfc995864d8c0987041300a22;hb=b142c68a1bc6ef1eb24fc61fed1b4bf702b4751f
[Preparing]: /var/tmp/php-build/source/5.3.3
[Info]: Applying patches: xp_ssl.c.patch zip_direct.c.patch
[Compiling]: /var/tmp/php-build/source/5.3.3
load: 2.53  cmd: clang 84977 running 0.14u 0.02s
load: 2.77  cmd: make 69356 waiting 0.08u 0.10s
load: 2.49  cmd: make 69356 waiting 0.12u 0.15s
[Pyrus]: Downloading from http://pear2.php.net/pyrus.phar
[Pyrus]: Installing executable in /Users/<hogehoge>/.phpenv/versions/5.3.3/bin/pyrus
[XDebug]: Downloading http://xdebug.org/files/xdebug-2.2.6.tgz
load: 2.39  cmd: curl 71067 waiting 0.00u 0.00s
[XDebug]: Compiling in /var/tmp/php-build/source/xdebug-2.2.6
[XDebug]: Installing XDebug configuration in /Users/<hogehoge>/.phpenv/versions/5.3.3/etc/conf.d/xdebug.ini
[XDebug]: Cleaning up.
[Info]: The Log File is not empty, but the Build did not fail. Maybe just warnings got logged. You can review the log in /tmp/php-build.5.3.3.20150108111746.log
[Success]: Built 5.3.3 successfully.
```

ちなみに、CONFIGURE_OPTSでPHPのconfigureオプションを指定している。さきほどインストールしたopensslのパスを設定している。

# phpenvコマンドを試す

**phpenv**コマンドをざっとまとめます。

### インストール可能なPHPバージョンを表示する

    $ phpenv install -l

上の方記述しているものと同じです。

### 選択できるPHPのバージョンを表示する

```
$ phpenv versions
  system
* 5.3.3 (set by /Users/hogehoge/.phpenv/version)
  5.4.36
  5.5.9
```
*で表示されているものがデフォルトで設定されているバージョン。

### バージョンを変更する(デフォルト)

デフォルトのPHPバージョンの設定は

    $ phpenv global <PHPバージョン>

例) 5.5.9をデフォルトのバージョンに設定する。

```
$ phpenv global 5.5.9
$ phpenv versions
  system
  5.3.3
  5.4.36
* 5.5.9 (set by /Users/hogehoge/.phpenv/version)
```

### 特定のディレクトリ配下のみで有効なPHPバージョンを設定する

     $ phpenv local <PHPバージョン>

例) /tmp/localのみ5.3.3を設定する。

```
$ pwd
/tmp/local
$ phpenv local 5.3.3
$ php -v
PHP 5.3.3 (cli) (built: Jan  8 2015 11:22:10)
...
$ $ phpenv versions
  system
* 5.3.3 (set by /tmp/local/.php-version)
  5.4.36
  5.5.9
```

これで、複数のPHPバージョンを気軽に切り替えられるようになりました。