PCがあれば何でもできる!

へっぽこアラサープログラマーが、覚えたての知識を得意げにお届けします

【OS X Yosemite(EI Capitan)】phpenv+phpbuild+apache2でPHPのバージョン切り替え

2015/11/20 追記
EI Capitanにアップデートすると/usrの書き込み権限がなくなったため、 apache2上で動作するPHPのバージョン切り替えから先の手順を変えました。

今日から、とある会社に転職するつもりが、ひょんな事からフリーランスになりました。
今後の予定は一応決まっているのですが、進展があったらまた書きたいと思います!

早速、今日はPHPを触るきっかけがあったのですが、PHPの環境構築時に、せっかくならrbenvっぽくバージョン管理したいなと思い、phpenvに手を出してみました。

で、気軽に始めてみたものの、まさかここまでハマることになろうとは…。

ざっくりですが、インストールした手順をメモっておきます。

環境

  • OS X Yosemite 10.10.2
  • apache2 Apache/2.4.9 (Unix)
    (Yosemiteセットアップ時に初期で入っていたもの)

brewでphpenvとphpbuildをインストール

その名の通り、"phpenv"はPHPのバージョン管理、"php-build"はPHPの各バージョンのビルドとインストールを担当します。

$ brew tap josegonzalez/homebrew-php
# ↑がないと、phpenvとphp-buildのformulaが見つからない。(Error: No available formula for phpenv)

$ brew install phpenv

$ brew install --HEAD php-build
# --HEADでmasterをDLしないとインストールできるPHPのバージョンリストが古い。

phpenvの環境変数を設定

.bashrcなどに記述する。

export PATH=$PATH:~/.phpenv/bin
eval "$(phpenv init -)"

source .bashrcなどで読み込ませると、phpenvを認識する。

phpbuildでのビルド前設定

/usr/local/share/php-build/default_configure_optionsに追記し、PHPビルド時のオプションを追加。

--with-apxs2 /usr/sbin/apxs

このオプションがないと、ビルド時にlibphp5.soが生成されない。
各バージョンのlibphp5.soをapache2に読み込ませることで、apache2上で動作するPHPのバージョンを切り替えることができる。

さらにビルドに必要なライブラリをインストール

$ brew install libjpeg
# ↑がないとビルド時にエラー(configure: error: jpeglib.h not found.)

$ brew install libpng
# ↑がないとビルド時にエラー(configure: error: png.h not found.)

$ brew reinstall libmcrypt
# ↑がないとビルド時にエラー(configure: error: mcrypt.h not found. Please reinstall libmcrypt.)

phpbuildで対象バージョンのPHPをビルド(ver 5.6.7の例)

$ php-build 5.6.7 ~/.phpenv/versions/5.6.7

第2引数はインストール場所。
上記の場合、libphp5.soは~/.phpenv/versions/5.6.7/libexec/apache2/libphp5.soに生成される。

phpenvでバージョン切り替え

$ phpenv global 5.6.7
$ phpenv rehash
$ php -v

apache2上で動作するPHPのバージョン切り替え

方法としては、php-buildでのビルド時に生成されたlibphp5.soをapache2に読み込ませるという形。

以前は、apache2が標準で読み込んでいる/usr/libexec/apache2/libphp5.soを直接置き換える方法を紹介していたが、EI Capitanになり書き込み権限がなくなったため、読み込むlibphp5.soのパスを変更する方法にする。

apache2で読み込まれるlibphp5.soのパスは、httpd.confに記載されているので、そこを書き換える。

ただ、バージョンの切り替え毎にhttpd.confでパス指定するのは面倒なので、ここでは/usr/local/libexec/apache2/libphp5.soに、対象のバージョンのlibphp5.soを配置することとする。

/etc/apache2/httpd.confを開き、以下のように書き換え。

#LoadModule php5_module libexec/apache2/libphp5.so
LoadModule php5_module /usr/local/libexec/apache2/libphp5.so

そして、指定のディレクトリにlibphp5.soをコピー。

#ディレクトリがなければ作成
sudo mkdir -p /usr/local/libexec/apache2

#コピー
sudo cp ~/.phpenv/versions/5.6.7/libexec/apache2/libphp5.so /usr/local/libexec/apache2/libphp5.so

最後に、sudo apachectl restartでapache2を再起動後、phpinfo()でphpのバージョンを確認して完了。

おまけ

手動でのlibphp5.soのコピーとapache2再起動が面倒な場合、phpenv-apache-versionというプラグインを使うと良いと紹介されているが、この環境だとまともに動かなかった。
そこでプラグインをインストール後に、少しスクリプトを修正。

# プラグインをインストール
$ git clone https://github.com/garamon/phpenv-apache-version ~/.phpenv/plugins/phpenv-apache-version

~/.phpenv/plugins/phpenv-apache-version/bin/rbenv-apache-versionの以下の2箇所を修正。

if command -v brew >/dev/null; then
#  if [ -d "$(brew --prefix httpd)" ]; then
#    PHPENV_APACHE_MODULE_PATH="$(brew --prefix httpd)/libexec"
#  fi
#else
#  if [ -f /etc/redhat-release ] ; then
#    PHPENV_APACHE_MODULE_PATH="/etc/httpd/modules"
#  elif [ -f /etc/debian_version ] ; then
#    PHPENV_APACHE_MODULE_PATH="/usr/lib/apache2/modules"
#  fi

  #apache2のモジュールのパスを固定に修正。
  PHPENV_APACHE_MODULE_PATH="/usr/local/libexec/apache2"
fi
#php-buildが生成するlibphp5.soのパスを正しいものに修正。
#PHP_MODULE_PATH="${PHPENV_PREFIX_PATH}/libphp5.so"
PHP_MODULE_PATH="${PHPENV_PREFIX_PATH}/libexec/apache2/libphp5.so"

後は、sudo phpenv apache-version 5.6.7のような形でバージョン切り替え可能。(コピー権限がいるのでsudoで)

2015/8/8 追記

追加で5.3.xをビルドしようとしたら、エラーが出たので追記します。

$ php-build 5.3.29 ~/.phpenv/versions/5.3.29

〜省略〜
configure: WARNING: You will need re2c 0.13.4 or later if you want to regenerate PHP parsers.
〜省略〜

re2cが足りないようなので、brewでインストールする。

$ brew install re2c

再チャレンジ。

$ php-build 5.3.29 ~/.phpenv/versions/5.3.29

〜省略〜
You've configured multiple SAPIs to be build. You can build only
one SAPI module and CLI binary at the same time.
〜省略〜

対処方法として、/usr/local/share/php-build/default_configure_optionsに以下のオプションを追記。

–disable-fpm

どうやら5.4.xと5.3.xでインストールされるphp-fpmのバージョンが違い、競合が発生している模様。 –disable-fpmオプションで同時にインストールしないようにすることで回避。

これで無事にビルド完了!