PHPbrewではじめるPHPのバージョン管理

公開日:

目次

MacOS を Monterey にアップデートしてからターミナル上で php コマンドや composer コマンドが実行できなくなってしまいました。調べてみると Monterey から PHP から標準インストールされなくなったようです。そのため、PHP を自前でインストールする必要があります。普通にインストールしてもよいのですが、せっかくならバージョン管理できるようになろうと思い、調べてみると PHP のバージョン管理では、PHPbrew というのが良いらしいので導入してみました。

PHPbrew とは

PHPbrew とは、 PHPのパッケージ管理ツールです。 Node.js でいう nodenv や volta とかと同じ立ち位置です。しかし、PHP のバージョンには nodenv のようにグローバル と ローカルという概念はなく、バージョンを変更したらOS全体でバージョンが変更されるようです。

必要要件

xcode と autoconf、pkg-config のインストール(xcodeは以前インストールしていればいらない)が必要です。インストールしてない方は以下のコマンドでインストールできます。

xcode-select --install
brew install autoconf pkg-config

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

brew install bison re2c

GETTING STARTED

インストール

curl -L -O https://github.com/phpbrew/phpbrew/releases/latest/download/phpbrew.phar
chmod +x phpbrew.phar

# $PATH の通っているディレクトリにファイルを移動します
sudo mv phpbrew.phar /usr/local/bin/phpbrew

初期化処理

シェルで bash スクリプトを初期化します。

phpbrew init

↑ コマンドを実行して、成功すると以下のようになります。

Initialization successfully finished!
<=====================================================>
Phpbrew environment is initialized, required directories are created under

    /Users/username/.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/username/.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!!

<=====================================================>

と出てくるので↓を実行

source /Users/username/.phpbrew/bashrc

## ↓でもok
source ~/.phpbrew/bashrc

.zshrc に以下を追加すると初期化処理をターミナル起動時に自動でやってくれます。

source $HOME/.phpbrew/bashrc

バリアントとは

公式から引用すると

PHPBrew は設定オプションをアレンジします。バリアント名を指定するだけで、 phpbrew がインクルードパスとビルドオプションを検出し、 設定を行ないます。

PHPBrew はデフォルトの variant といくつかの仮想 variant を提供しています。よく使われる variant を含むデフォルト variant と、variant セットを定義する仮想 variant で、ひとつの仮想 variant を使って複数の variant を一度に有効にすることができます。

これらの variant に何が含まれているかを調べるには、 phpbrew variants を実行してこれらの variant をリストアップします。

つまり、バリアントとはPHPをインストールする際に必要なパッケージのことで、以下のようにインストール時のコマンドと一緒に記述することで一緒にインストールしてくれるということです。

phpbrew install 5.4.1 +pgsql+pdo

そして、 仮想 variant とはよく使用する variant をパッケージとしてまとめたもの。以下のコマンドで確認できます。

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

基本操作

PHP のバージョンを一覧する:

phpbrew known
Read local release list (last update: 2022-02-24 03:14:45 UTC).
You can run `phpbrew update` or `phpbrew known --update` to get a newer release list.
8.1: 8.1.3, 8.1.2, 8.1.1, 8.1.0 ...
8.0: 8.0.16, 8.0.15, 8.0.14, 8.0.13, 8.0.12, 8.0.11, 8.0.10, 8.0.9 ...
7.4: 7.4.28, 7.4.27, 7.4.26, 7.4.25, 7.4.24, 7.4.23, 7.4.22, 7.4.21 ...
7.3: 7.3.33, 7.3.32, 7.3.31, 7.3.30, 7.3.29, 7.3.28, 7.3.27, 7.3.26 ...
7.2: 7.2.34, 7.2.33, 7.2.32, 7.2.31, 7.2.30, 7.2.29, 7.2.28, 7.2.27 ...
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 ...

現在インストールされている PHP バージョンが、php 8.1.3で phpbrew known を実行すると、 Deprecated: strpos(): のようなwarningが出まくるので注意です。7.3.33 に落とすとでこのwarningは出なくなりました。

PHPのビルド(インストール)

phpbrew install 7.4.25 +default

ビルド(インストール)が成功すると、以下のようになります。

config-set succeeded
config-set succeeded
config-set succeeded
Enabling pear auto-discover...
config-set succeeded
Congratulations! Now you have PHP with 7.4.25 as php-7.4.25

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

* WARNING:
  You haven't setup your .bashrc file to load phpbrew shell script yet!
  Please run 'phpbrew init' to see the steps!

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

    $ phpbrew use php-7.4.25

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

    $ phpbrew switch php-7.4.25

Enjoy!

インストールされているPHPの一覧

phpbrew list
* (system)
  php-7.4.25

use (一時的なバージョンの切り替え)

phpbrew use php-7.4.25

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

phpbrew switch php-7.4.25

phpbrewを使用するのをやめる(システムデフォルトのPHPを使用)

phpbrew off

トラブルシューティング

php 8.0.16 をインストールしようとしたら下記エラーがでました。

phpbrew install 8.0.16 +default
===> phpbrew will now build 8.0.16
===> Loading and resolving variants...
Homebrew prefix "/usr/local/opt/libxml2" does not exist.
Homebrew prefix "/usr/local/opt/bzip2" does not exist.
Homebrew prefix "/usr/local/opt/mhash" does not exist.
Homebrew prefix "/usr/local/opt/openssl@3" does not exist.
Downloading https://www.php.net/distributions/php-8.0.16.tar.bz2 via curl extension
[==================================================================] 12.88/12.88MB 100%
===> Extracting /Users/username/.phpbrew/distfiles/php-8.0.16.tar.bz2 to /Users/uirikuto/.phpbrew/build/tmp.1645877003/php-8.0.16
===> Moving /Users/username/.phpbrew/build/tmp.1645877601/php-8.0.16 to /Users/uirikuto/.phpbrew/build/php-8.0.16
===> 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
===> Configuring 8.0.16...


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


Error: Configure failed:
The last 5 lines in the log file:
installed software in a non-standard prefix.



Alternatively, you may set the environment variables OPENSSL_CFLAGS

and OPENSSL_LIBS to avoid the need to call pkg-config.

See the pkg-config man page for more details.

Please checkout the build log file for more details:
	 tail /Users/username/.phpbrew/build/php-8.0.16/build.lo

ログを確認してみると、openssl というパッケージが足りてないと言われました。

tail /Users/username/.phpbrew/build/php-8.0.16/build.log
configure: error: Package requirements (openssl >= 1.0.1) were not met:

No package 'openssl' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables OPENSSL_CFLAGS
and OPENSSL_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

とりあえず、現在のopensslのバージョンを確認してみました。

openssl version
LibreSSL 2.8.3

MacのHigh Sierraから、デフォルトのOpenSSLがOpenSSLからLibreSSLになっているため、LibreSSL が使用されているようです。

詳しくはこちら

とりあえず、brew list で現在homebrew でインストールしているパッケージを確認してみると、openssl@1.1 はインストールされているようです。

brew list
==> Formulae
aom			curl			glib			jpeg			libpng			libxcb			oniguruma		re2c
apr			docbook			gmp			jpeg-xl			libpq			libxdmcp		openexr			readline
apr-util		docbook-xsl		gnu-getopt		krb5			libpthread-stubs	libxext			openjpeg		rtmpdump
argon2			emacs			gnutls			libavif			libsodium		libxrender		openldap		shared-mime-info
aspell			fontconfig		gobject-introspection	libde265		libspiro		libzip			openssl@1.1		sqlite
autoconf		freetds			graphite2		libev			libssh2			little-cms2		p11-kit			tidy-html5
bdw-gc			freetype		guile			libevent		libtasn1		lzo			pango			unbound
bison			fribidi			harfbuzz		libffi			libtiff			m4			pcre			unixodbc
brotli			gd			icu4c			libheif			libtool			mpdecimal		pcre2			webp
c-ares			gdbm			imagemagick		libidn			libuninameslist		nettle			php			x265
ca-certificates		gettext			imath			libidn2			libunistring		nghttp2			php@7.3			xmlto
cairo			ghostscript		jansson			liblqr			libvmaf			node-build		pixman			xorgproto
cask			giflib			jbig2dec		libnghttp2		libx11			nodebrew		pkg-config		xz
coreutils		git			jemalloc		libomp			libxau			nodenv			python@3.9		zstd

==> Casks
alfred			cheatsheet		dropbox			google-backup-and-sync	iterm2			sketch			zoom
biscuit			clipy			firefox			google-japanese-ime	mamp			visual-studio-code

一応インストールしてみます。

brew install openssl

インストール後、もう一度 php 8.0.16 をインストールすると、今度は以下のエラーが…

phpbrew install 8.0.16 +default
===> phpbrew will now build 8.0.16
===> Loading and resolving variants...
Homebrew prefix "/usr/local/opt/libxml2" does not exist.
Homebrew prefix "/usr/local/opt/bzip2" does not exist.
Homebrew prefix "/usr/local/opt/mhash" does not exist.
Checking distribution checksum...
Checksum matched: f49f8181ee29463a0d23a0c65969e92d58fee8ac564df917cff58e48d65e1849
===> 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/username/.phpbrew/build/php-8.0.16/build.log.1645877638
===> Configuring 8.0.16...


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


Error: Configure failed:
The last 5 lines in the log file:
checking for ZLIB support... no

checking whether to enable bc style precision math functions... yes

checking for BZip2 support... yes

checking for BZip2 in default path... not found

configure: error: Please reinstall the BZip2 distribution

Please checkout the build log file for more details:
	 tail /Users/username/.phpbrew/build/php-8.0.16/build.log

まず、最初の Homebrew prefix 〇〇 というところから必要パッケージが足りてないのではないかと思い homebrew でインストールしました。

brew install libxml2 bzip2 mhash
再度、php 8.0.16 をインストールしてみると、またエラーが…
phpbrew install 8.0.16 +default
===> phpbrew will now build 8.0.16
===> Loading and resolving variants...
Checking distribution checksum...
Checksum matched: f49f8181ee29463a0d23a0c65969e92d58fee8ac564df917cff58e48d65e1849
===> 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/username/.phpbrew/build/php-8.0.16/build.log.1645878692
===> Configuring 8.0.16...


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


===> Checking patches...
Checking patch for php5.3.x on 64bit machine when intl is enabled.
Checking patch for openssl dso linking patch
2 changes patched.
Checking patch for php5.6 with openssl 1.1.x patch.
===> Building...
Error: Make failed:
The last 5 lines in the log file:
/usr/local/Cellar/openssl@3/3.0.1/include/openssl/rsa.h:289:29: note: passing argument to parameter 'rsa' here

                       RSA *rsa, int padding);

                            ^

108 warnings and 1 error generated.

make: *** [ext/openssl/openssl.lo] Error 1

Please checkout the build log file for more details:
	 tail /Users/username/.phpbrew/build/php-8.0.16/build.log

ログを見ても、よくわかりません。。。

tail /Users/usename/.phpbrew/build/php-8.0.16/build.log
#     define OSSL_DEPRECATED(since) __attribute__((deprecated))
                                                   ^
/Users/username/.phpbrew/build/php-8.0.16/ext/openssl/openssl.c:6393:6: warning: passing 'const struct rsa_st *' to parameter of type 'RSA *' (aka 'struct rsa_st *') discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
                                        EVP_PKEY_get0_RSA(pkey),
                                        ^~~~~~~~~~~~~~~~~~~~~~~
/usr/local/Cellar/openssl@3/3.0.1/include/openssl/rsa.h:289:29: note: passing argument to parameter 'rsa' here
                       RSA *rsa, int padding);
                            ^
108 warnings and 1 error generated.
make: *** [ext/openssl/openssl.lo] Error 1

調べると、以下の記事がヒットしましたが、一旦opensslがまだhomebrewでインストールしたほうを参照してくれていないのではないかと思ったので whtch コマンドで確認します。

which openssl
/usr/bin/openssl

openssl version
LibreSSL 2.8.3

そうするとやっぱり思ったとおりで、 openssl の参照先が違っていました。なので、openssl@3のパスを通してあげます。

echo 'export PATH="/usr/local/opt/openssl@3/bin:$PATH"' >> ~/.zshrc

ターミナルを立ち上げ直すか、souce ~/.zshrc をしてから確認すると、v3が参照されるようになっている

openssl version
OpenSSL 3.0.1 14 Dec 2021 (Library: OpenSSL 3.0.1 14 Dec 2021)

ここで再度、phpのインストールをしてみるが、同じエラー…。openssl v3 を参照しているのが駄目なのかと思い、.zshrc の openssl@3 を @1.1 に変更します。

# ~/.zshrc
export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"

openssl がv1.1 を参照していることを確認して再度 php のインストールを試みるも解決せず…

openssl version
OpenSSL 1.1.1m &nbsp;14 Dec 2021

最終的な解決策として、.zshrc に以下を追加して解決でした。

export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"

このブログ記事に助けられました。ありがとうございます?

phpbrew install 7.4.25 +default
===> phpbrew will now build 7.4.25
===> Loading and resolving variants...
Homebrew prefix "/usr/local/opt/openssl@3" does not exist.
Checking distribution checksum...
Checksum matched: 27992570caf3e2e5323ab7b37853c44c1529b1d31ea94d9776efa91d5a781313
===> 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/uirikuto/.phpbrew/build/php-7.4.25/build.log.1645882512
===> Configuring 7.4.25...


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


===> Checking patches...
Checking patch for php5.3.x on 64bit machine when intl is enabled.
Checking patch for openssl dso linking patch
0 changes patched.
Checking patch for php5.6 with openssl 1.1.x patch.
===> Building...
Build finished: 7.4 minutes.
Installing...
---> Creating php-fpm.conf
---> Creating php.ini
---> Copying /Users/username/.phpbrew/build/php-7.4.25/php.ini-development
---> Found date.timezone is not set, patching...
Initializing pear config...
config-set succeeded
config-set succeeded
config-set succeeded
Enabling pear auto-discover...
config-set succeeded
Congratulations! Now you have PHP with 7.4.25 as php-7.4.25

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

* WARNING:
  You haven't setup your .bashrc file to load phpbrew shell script yet!
  Please run 'phpbrew init' to see the steps!

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

    $ phpbrew use php-7.4.25

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

    $ phpbrew switch php-7.4.25

Enjoy!

openssl@3 はいらなくなったのでアンインストール済みです。

brew uninstall openssl@3
Uninstalling /usr/local/Cellar/openssl@3/3.0.1... (6,420 files, 28.1MB)

Warning: The following openssl@3 configuration files have not been removed!
If desired, remove them manually with `rm -rf`:
  /usr/local/etc/openssl@3
  /usr/local/etc/openssl@3/cert.pem
  /usr/local/etc/openssl@3/certs
  /usr/local/etc/openssl@3/ct_log_list.cnf
  /usr/local/etc/openssl@3/ct_log_list.cnf.dist
  /usr/local/etc/openssl@3/misc
  /usr/local/etc/openssl@3/misc/CA.pl
  /usr/local/etc/openssl@3/misc/tsget
  /usr/local/etc/openssl@3/misc/tsget.pl
  /usr/local/etc/openssl@3/openssl.cnf
  /usr/local/etc/openssl@3/openssl.cnf.dist
  /usr/local/etc/openssl@3/private

Warning: The following may be openssl@3 configuration files and have not been removed!
If desired, remove them manually with `rm -rf`:
  /usr/local/etc/openssl@1.1

~/develop/workspace/phpbrew-test
❯ brew list
==> Formulae
aom			curl			gmp			krb5			libsodium		libxrender		openldap		sqlite
apr			docbook			gnu-getopt		libavif			libspiro		libzip			openssl@1.1		tidy-html5
apr-util		docbook-xsl		gnutls			libde265		libssh2			little-cms2		p11-kit			unbound
argon2			emacs			gobject-introspection	libev			libtasn1		lzo			pango			unixodbc
aspell			fontconfig		graphite2		libevent		libtiff			m4			pcre			webp
autoconf		freetds			guile			libffi			libtool			mhash			pcre2			x265
bdw-gc			freetype		harfbuzz		libheif			libuninameslist		mpdecimal		php			xmlto
bison			fribidi			icu4c			libidn			libunistring		nettle			php@7.3			xorgproto
brotli			gd			imagemagick		libidn2			libvmaf			nghttp2			pixman			xz
bzip2			gdbm			imath			liblqr			libx11			node-build		pkg-config		zstd
c-ares			gettext			jansson			libnghttp2		libxau			nodebrew		python@3.9
ca-certificates		ghostscript		jbig2dec		libomp			libxcb			nodenv			re2c
cairo			giflib			jemalloc		libpng			libxdmcp		oniguruma		readline
cask			git			jpeg			libpq			libxext			openexr			rtmpdump
coreutils		glib			jpeg-xl			libpthread-stubs	libxml2			openjpeg		shared-mime-info

==> Casks
alfred			cheatsheet		dropbox			google-backup-and-sync	iterm2			sketch			zoom
biscuit			clipy			firefox			google-japanese-ime	mamp			visual-studio-code

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/cert.pem

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/certs

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/ct_log_list.cnf

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/ct_log_list.cnf.dist

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/misc

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/misc/CA.pl

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/misc/tsget

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/misc/tsget.pl

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/openssl.cnf

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/openssl.cnf.dist

~/develop/workspace/phpbrew-test
❯ rm -rf /usr/local/etc/openssl@3/private

まとめ

PHP のバージョン管理をするだけでエラーと格闘してとてもめんどくさかったですw PHPbrew に比べると、nodenv や volta は楽ちんでいいなと思いました。

参考記事

PHPbrew のGithub