🐘

[Mac] phpenv+nodebrewでローカル開発環境を作る手順(保存版)

2020/02/15に公開
1

こんにちは、たつきちです。

PHPer歴10年近くになりますが、僕のPHP開発環境は今のところphpenvnodebrewに落ち着いています。

この記事では、phpenv+nodebrewのローカル開発環境の構築手順をまとめてみたいと思います。

ぜひ最後までお付き合いください。

なお、本記事はmacOS向けの説明になります🙏

その他のOSをお使いの方は、適宜読み替えながら参考にしていただければと思います。

phpenv

まずはphpenvから、順を追って解説していきます。

はじめに

phpenvによるPHPのインストールは、インストールしようとするバージョンによって細かい対応が必要な場合があります。

以下のページに本ブログ内の関連記事をまとめていますので、必要に応じてご参照ください🙏

[2020年末版] Macでのphpenv(php-build)によるPHP 5.6〜8.0のインストール方法まとめ

基本的なインストール手順

まず、以下のコマンドを実行して phpenv 本体をインストールします。

$ git clone git://github.com/phpenv/phpenv.git ~/.phpenv

次に、PATHの設定とコマンドの自動補完などのために、シェルのプロファイル( ~/.bash_profile~/.zshrc など)に以下の2行を追記して、シェルを再起動します。

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

さらに、以下のコマンドを実行して、phpenvのプラグインとして php-build を使えるようにします。

$ git clone https://github.com/php-build/php-build $(phpenv root)/plugins/php-build

これで、基本的な準備は整いました。

以下のコマンドを実行すると、インストール可能なPHPのバージョンを一覧で確認できます。

$ phpenv install --list

実際にPHPをインストールしてみる

試しに7.4系の最新(記事執筆時点)をインストールしてみましょう。(ソースのダウンロードとコンパイルでかなり時間がかかります)

$ phpenv install 7.4.13

どうですか?たぶん、

No package 'xxx' found

といったエラーでインストールが失敗したのではないでしょうか。

実は、PHPをMac上でソースからコンパイルするには、必要な依存がかなり大量にあるので、それらを事前にきっちりインストールしておく必要があるのです🙄

依存ライブラリをインストール

具体的には、homebrewで以下をインストールしておけばほとんどのバージョンがインストールできるようになると思います。

もし足りなければ、エラーメッセージに従って追加でインストールしてあげれば解決できるかと思います。

$ brew install bison bzip2 curl icu4c krb5 libedit libiconv libmcrypt libxml2 libzip oniguruma openssl@1.1 pkg-config re2c zlib

参考:ソースコード(php-src)からPHPをビルドする流れと仕組みを手を動かしながら理解する

なお、bisonについては、Homebrewが自動でPATHを通してくれないようで、自分でPATHを通す必要があります。シェルのプロファイルに以下の1行を追記しておきましょう。

export PATH=/usr/local/opt/bison/bin:$PATH

PHP7.4系以上をインストールする場合は、環境変数 PKG_CONFIG_PATH の設定が必要

また、7.4系以上をインストールする場合、依存ライブラリをインストールするだけでは足りず、インストールされているライブラリを見つけてもらうために PKG_CONFIG_PATH という環境変数を適切に設定しておく必要があるようです。

参考:macOS上でphp-buildからmasterをビルドする(PHP 7.4+編) - Qiita

具体的には、シェルのプロファイルに以下の1行を追記すればOKです。

もし足りなければ、エラーメッセージを見て適切に追記してあげれば解決できるかと思います。

PKG_CONFIG_PATH=/usr/local/opt/krb5/lib/pkgconfig:/usr/local/opt/openssl/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libedit/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig

これで、再度インストールしてみてください。今度は上手くいくのではないかと思います👍

Mojave以降のMacで必要となる対応

と言いつつ、このままではまだインストール成功していない人が多いと思います。

実は、Mojave以降のmacOSでは、 phpenv install しようとすると

configure: error: Cannot find zlib

と言われてインストールできません。

このエラーは、macOSのバージョンによって対処方法が異なります。

上記サイトが参考になります。

ここではCatalinaでの対処方法について記しておきます。(2020年12月時点で、Big Surでも同様の対応で大丈夫そうです)

参考サイトにあるとおりですが、PHPをコンパイルする際のオプションを変更して、zlibを含む各種ライブラリのパスを明示してあげることでコンパイルできるようになります。

コンパイルオプションは PHP_BUILD_CONFIGURE_OPTS という環境変数で指定することができるので、(すごく長いですが)以下のようなコマンドでインストールを実行すれば正常にコンパイル可能になります。

インストールするPHPのバージョンや導入するPHP拡張によって必要な設定は多少変わってきます。経験的に以下の内容で大体のケースに対応できると思っていますが、ご自身のインストール対象で上手くいかない場合は、エラーメッセージを見て適切に追記してあげれば解決できるかと思います。

PHP_BUILD_CONFIGURE_OPTS="--with-zlib-dir=/usr/local/opt/zlib --with-bz2=/usr/local/opt/bzip2 --with-iconv=/usr/local/opt/libiconv --with-curl=/usr/local/opt/curl --with-libedit=/usr/local/opt/libedit --with-jpeg-dir=/usr/local/opt/libjpeg --with-png-dir=/usr/local/opt/libpng" \
phpenv install {バージョン}

一行目を見やすいように展開すると以下の内容になっています。

--with-zlib-dir=/usr/local/opt/zlib
--with-bz2=/usr/local/opt/bzip2
--with-iconv=/usr/local/opt/libiconv
--with-curl=/usr/local/opt/curl
--with-libedit=/usr/local/opt/libedit
--with-jpeg-dir=/usr/local/opt/libjpeg
--with-png-dir=/usr/local/opt/libpng

ちなみに、phpenvからphp-buildにデフォルトで渡すコンパイルオプションのリストは

~/.phpenv/plugins/php-build/share/php-build/default_configure_options

この設定ファイルで定義されているので、このファイルに上記のオプションを追記しておくことでも同様の結果が得られます。

しかしながら、参考サイトにも書いてあるとおり、設定ファイルに追記しても libedit だけは効かないケースがあるようで、その場合は結局 libedit についてだけは環境変数で明示的に指定する必要があります😓

PHP_BUILD_CONFIGURE_OPTS="--with-libedit=/usr/local/opt/libedit" phpenv install {バージョン}

なので、どうせなら先に紹介した長い1行にaliasを設定しておくといった対応のほうがシンプルかと思います。

ついでに PHP_BUILD_EXTRA_MAKE_ARGUMENTS=-j4 のようにコンパイル処理の並列数を増やすオプションを付けておくと、コンパイルにかかる時間を短縮できておすすめです。

インストールしたPHPを有効化

さて、無事にインストールが完了したら、 phpenv versions コマンドでインストール済みのバージョンが一覧で見られます。

$ phpenv versions
* system (set by /Users/{user}/.phpenv/version)
  7.4.13

無事インストールされています👍

* が付いているのが現在使用中のバージョンです。今は system が選択されていますね。これは、OS標準のPHPや、homebrewでインストールしたPHPなど、phpenvのPATHよりも先に読み込まれているPHPを指しています。

実際に使いたいPHPのバージョンを指定するには、 phpenv global コマンドを使います。

$ phpenv global 7.4.13
7.4.13

# 使えるようになっていることを確認
$ php -v
PHP 7.4.13 (cli) (built: Dec  6 2020 23:55:05) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.13, Copyright (c), by Zend Technologies
    with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans

もしかすると、この時点で php -v すると dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.64.dylib のようなエラーになる方がいらっしゃるかもしれません。

このエラーの対処法は後述しますので、いったんスルーしておいてください。

phpenv global で簡単に別のバージョンに切り替えられます。

$ PHP_BUILD_CONFIGURE_OPTS="..." phpenv install 7.3.25

# しばらく待つ

$ phpenv global 7.3.25
7.3.25

# 使えるようになっていることを確認
PHP 7.3.25 (cli) (built: Dec  6 2020 21:18:27) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.25, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.25, Copyright (c) 1999-2018, by Zend Technologies
    with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans

ちなみに、 phpenv local {バージョン} コマンドを使えば、システム全体ではなくカレントディレクトリ配下のみで特定のバージョンのPHPを使うこともできます。

実行すると .php-version というファイルが作成されます。無効にしたい場合はこのファイルを削除すればOKです。

その他のよくあるエラー

その他、phpenv導入時によく起こるエラーについても簡単にまとめておきますので、インストールでつまずいた方は参考にしてみてください✋

dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.64.dylib

phpenvでインストールしたPHPが突然以下ようなエラーを吐くケースがあります。

dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.64.dylib
  Referenced from: /path/to/bin/node
  Reason: image not found

このエラーは、icu4cというライブラリのバージョンを切り替えることで解決できます。

どうも、PHP7.4系を使う場合はicu4cのバージョンは64系が必要で、PHP7.3系以下を使う場合はicu4cのバージョンは63系が必要なようです。(体験談)

具体的な手順は以下の別記事にまとめてありますので、そちらをご参照ください。

PHPが突然Library not loaded: /path/to/libicui18n.64.dylibとか言い出したときの対処法

PHP拡張をインストールする方法

以下の過去記事で紹介しているのでご参照ください。

phpenv(php-build)でapcuなどのPHP拡張をインストールする方法 | blog.ttskch.com

aliasを設定するかスクリプト化しておくと便利

phpenv install 時に必要なオプションが大量なので、例えば以下のような感じで phpenv-install などでaliasを設定しておくと便利です。

# .zshrc
alias phpenv-install='PHP_BUILD_INSTALL_EXTENSION="@apcu @imagick" PHP_BUILD_EXTRA_MAKE_ARGUMENTS=-j4 PHP_BUILD_CONFIGURE_OPTS="--with-zlib-dir=/usr/local/opt/zlib --with-bz2=/usr/local/opt/bzip2 --with-jpeg-dir=/usr/local/opt/libjpeg --with-png-dir=/usr/local/opt/libpng --with-curl=/usr/local/opt/curl --with-iconv=/usr/local/opt/libiconv --with-libedit=/usr/local/opt/libedit" phpenv install'

インストールするPHP拡張も引数で指定したり、 php.ini の内容をついでに調整したり、より柔軟に対応できるようにスクリプトにしておくのもいいと思います。

参考までに僕が使っているスクリプトは以下のような感じです。これを phpenv-install というファイル名でパスの通っている場所に設置します。

#!/bin/sh

if [ $# -eq 0 ]; then
    echo "Usage: phpenv-install <version> [extensions]"
    exit 1
else
    VERSION=$1
fi

if [ $# -eq 1 ] ; then
    EXTENSIONS="apcu=@ imagick=@"
else
    EXTENSIONS=${2:-""}
fi

export PATH=/usr/local/opt/bison/bin:$PATH
export PKG_CONFIG_PATH=/usr/local/opt/krb5/lib/pkgconfig:/usr/local/opt/openssl/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libedit/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig

export PHP_BUILD_INSTALL_EXTENSION="$EXTENSIONS"
export PHP_BUILD_EXTRA_MAKE_ARGUMENTS=-j4
export PHP_BUILD_CONFIGURE_OPTS="--with-zlib-dir=/usr/local/opt/zlib --with-bz2=/usr/local/opt/bzip2 --with-jpeg-dir=/usr/local/opt/libjpeg --with-png-dir=/usr/local/opt/libpng --with-curl=/usr/local/opt/curl --with-iconv=/usr/local/opt/libiconv --with-libedit=/usr/local/opt/libedit"
phpenv install $VERSION

if [ -e ~/.phpenv/versions/$VERSION/etc/php.ini ] ; then
    gsed -i -E "s/^;?(max_execution_time) *=.*$/\1 = 0/g" ~/.phpenv/versions/$VERSION/etc/php.ini
    gsed -i -E "s/^;?(max_input_time) *=.*$/\1 = -1/g" ~/.phpenv/versions/$VERSION/etc/php.ini
    gsed -i -E "s/^;?(memory_limit) *=.*$/\1 = 512M/g" ~/.phpenv/versions/$VERSION/etc/php.ini
    gsed -i -E "s/^;?(date.timezone) *=.*$/\1 = Asia\/Tokyo/g" ~/.phpenv/versions/$VERSION/etc/php.ini
    gsed -i -E "s/^;?(mbstring.internal_encoding) *=.*$/\1 = UTF-8/g" ~/.phpenv/versions/$VERSION/etc/php.ini
fi

こうしておけば、

phpenv-install 7.4.13

という感じで簡単にインストールを実行できます。

その他参考記事

phpenv+php-buildによるPHPのインストールについて、以下のページが詳細に説明されていて参考になります。

phpenv & php-build で macOS Catalina に複数バージョンの PHP 環境を構築する

nodebrew

では次に、nodebrewについて見ていきましょう。

こちらはphpenvと比べるとほとんどつまずきポイントがなくてあっさり完了すると思います👍

インストール手順

まず、homebrewなどですでにnodeがインストールされている場合は、アンインストールが必要です。

$ brew uninstall node

nodeがない状態になったら、nodebrewをインストールします。

$ brew install nodebrew

# インストールされたことを確認
$ nodebrew -v
nodebrew 1.0.1

インストールしたら、少しだけ初期設定が必要です。

$ nodebrew setup

これを実行すると、

Fetching nodebrew...
Installed nodebrew in $HOME/.nodebrew

========================================
Export a path to nodebrew:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================

のように出力されると思います。

nodebrew経由でインストールするnodeの設置先である ~/.nodebrew ディレクトリを作ってくれただけです。

メッセージに表示されているとおりPATHの設定が必要なので、シェルのプロファイルに以下の1行を追記しておきましょう。

export PATH=$HOME/.nodebrew/current/bin:$PATH

これで準備が整いました。

実際にnodeをインストールしてみる

最新のnodeを入れてみましょう。

$ nodebrew ls-remote

でインストール可能なバージョンが一覧表示されます。

試しに、12系と13系の最新(記事執筆時点)を入れてみましょう。

$ nodebrew install v12
$ nodebrew install v13

バージョン番号は以下のように柔軟に指定できます。(参考

$ nodebrew install v12.20.0 # 12.20.0 指定
$ nodebrew install 12.20.0 # `v` がなくてもOK
$ nodebrew install latest # 最新版
$ nodebrew install stable # 安定板
$ nodebrew install v12.20 # 12.20系の最新版
$ nodebrew install v12 # 12系の最新版

nodebrew ls コマンドでインストール済みのバージョンが一覧で見られます。

$ nodebrew ls
v12.20.0
v13.14.0

current: none

無事インストールされています👍

インストールしたnodeを有効化

現状だと、 current: none となっているとおり、「インストールされているnodeのうちどれを使うか」がまだ設定されていない状態なので、 nodebrew use コマンドで実際に使えるようにします。

$ nodebrew use v12 # ここでもインストール時と同じバージョン番号指定が可能
use v12.20.0

# 使えるようになっていることを確認
$ node -v
v12.20.0

nodebrew use で簡単に別のバージョンに切り替えられます。

$ nodebrew use v13
use v13.14.0
$ node -v
v13.14.0

まとめ

PHPとnodeのバージョンを自由に切り替えながら開発できる環境は、ある程度本格的に開発をしていく上では必須かなと思います。

phpenv+nodebrew以外にも色々なソリューションがありますが、今回は僕が実際に使っている環境の構築方法をまとめてお伝えしました。

参考になれば幸いです!

GitHubで編集を提案

Discussion

LeslieLeslie

ServBay.devというツールを見つけました。特に初心者のPHP開発者にとっては、非常に簡単な方法を提供しています。PHPの全バージョン、MariaDB、PostgreSQL、Redis、およびMemcachedが含まれています。ユーザーは複数のPHPインスタンスを同時に実行することができます。