PHP7でMongoDB:環境構築編
10年くらい前に作ったちょっとした社内システムをアップデートすることになった。
はてなダイアリーでこのブログを書いてた頃に作ったものだったかな。
社内サーバーのリプレイスに伴うもので、4年に1回くらいは引越ししてたけど、今回はOSプリインストールのPHPとMongoDBのバージョンが上がってしまって互換性がなくなり、動かなくなってしまった。まあ、PHP7系になってMongoDBにアクセスできなくなってしまったんだけど。
この茨の道は記録しておいたほうがいいだろう。
(作業期間は2020年1月から2月)
【テストサーバーで試す】
社内サーバーはUbuntuで、サーバー管理者がテストサーバーを用意してくれた。
ブラウザで表示はできるが、MongoDBにアクセスしようとするとエラーが出る。
Apacheのログには、
PHP Fatal error: Uncaught Error: Class 'Mongo' not found in ...
とか何とか。
info.phpを表示してみると、MongoDBの情報は出ていない。
WSL (Ubuntu 16.04 TLS) 内で、PHPから MongoDB を操作する環境を作る
とりあえず、php.iniに、
extension=mongo.so
を追記してみる。
確認:
$ php -m | grep mongo
PHP Warning: PHP Startup: Unable to load dynamic library 'mongo.so' (tried: /usr/lib/php/20170718/mongo.so (/usr/lib/php/20170718/mongo.so: cannot open shared object file: No such file or directory), /usr/lib/php/20170718/mongo.so.so (/usr/lib/php/20170718/mongo.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
確かに、
/usr/lib/php/20170718
にmongo.soがない。
PHPのバージョンは7.2だったので、PHP7.2用のMongoDBドライバをインストールする。
$ sudo apt install php7.2-dev
いろいろ吐いてる。
続いて、MongoDBのドライバをインストール:
$ sudo pecl install mongodb
/usr/lib/php/20170718/mongodb.so
が入った。
うん?mongo.soじゃなくて、mongodb.soなの?
php.iniのextensionの記述を変更してみる。
extension=/usr/lib/php/20170718/mongodb.so
再度、確認:
$ php -m | grep mongo
mongodb
apacheを再起動。
$ sudo service apache2 restart
やっぱりinfo.phpにMongoDBの情報は出てこない。
とりあえず、テストサーバーでの作業はここで中断。
後日、サーバー管理者がテストサーバーを構築しなおした際、以下でinfo.phpにMongoDBが表示されるようになった。
$ sudo apt install mongodb
$ sudo apt install php7.2-dev
$ sudo pecl install mongodb
php.iniは、
extension=mongodb.so
でよかったよかった。
【macに環境を作る】
やっぱり手元で作業できないと面倒だな、と思って、普段使っているmacに開発環境を作ろうとする。
macOSのバージョンはCatalina。
まずは、MongoDBのインストール。
brewからmongodbがなくなったのでmongodb-communityをインストールする
へ?
% brew search mongodb
==> Casks homebrew/cask-versions/mongodb-compass-beta homebrew/cask/gcollazo-mongodb homebrew/cask/mongodb-compass homebrew/cask/mongodb-compass-community homebrew/cask/mongodb-compass-isolated-edition homebrew/cask/mongodb-compass-readonly homebrew/cask/nosqlbooster-for-mongodb
へー、そうなんですか。
brew tapを使ってbrew installできるようにして、と。
% brew tap mongodb/brew
mongoldb-comunityをインストールする。
% brew install mongodb-community
MongoDB開始。
% brew services start mongodb-community
==> Successfully started `mongodb-community` (label: homebrew.mxcl.mongodb-commu
クライアントを起動してみる。
% mongo
MongoDB shell version v4.2.3 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb …
MongoDBのインストールはできた。
続いて、PHPからMongoDBにアクセスするためにPHP用のMongoDBのドライバをインストールする必要があるんだが、peclというのを使ってインストールするらしく、それはpearを入れれば一緒に入る、とのことらしいんだが、pearがオワコンという情報もあり、どうしたものかね。
と、調べていると、peclの代替でpickleというのがあるそうで、これを使ってみますか。
pickle - PHP Extension installer
pickleはcomposerというのを使ってインストールするらしいので、まずはcomposerをインストールしてみる。
% curl -sS https://getcomposer.org/installer | php
composer.pharというのがダウンロードされたので、こいつを/usr/local/binに移動させる。
(composer.pharがあるディレクトリに移動して、と)
% mv composer.phar /usr/local/bin/composer
確認:
% which composer
/usr/local/bin/composer
続いてgithubからpickle(pickle-master.zip)をダウンロードする。
解凍すると、pickle-masterというディレクトリができる。
これがインストーラーらしい。
ターミナルでpickle-masterディレクトリに移動して、インストールする。
% composer install
Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages. Problem 1 - The requested PHP extension ext-zip * is missing from your system. Install or enable PHP's zip extension.
ext-zipって何だ?
Laravel環境構築php-zip(ext-zip)のインストールについて
プリインストールのphpではなく、homebrewでインストールしたphpを使えと。。。
% brew search php
==> Formulae brew-php-switcher php-cs-fixer phplint phpstan php php@7.2 phpmd phpunit php-code-sniffer php@7.3 phpmyadmin ==> Casks homebrew/cask/eclipse-php homebrew/cask/netbeans-php
まあ、別にUbuntuに合わせなくてもいいから、7.3にしますか。
% brew install php@7.3
長々といろいろと吐かれるが、最後にいろいろと大事なことが。
The php.ini and php-fpm.ini file can be found in: /usr/local/etc/php/7.3/ php@7.3 is keg-only, which means it was not symlinked into /usr/local, because this is an alternate version of another formula. If you need to have php@7.3 first in your PATH run: echo 'export PATH="/usr/local/opt/php@7.3/bin:$PATH"' >> ~/.zshrc echo 'export PATH="/usr/local/opt/php@7.3/sbin:$PATH"' >> ~/.zshrc For compilers to find php@7.3 you may need to set: export LDFLAGS="-L/usr/local/opt/php@7.3/lib" export CPPFLAGS="-I/usr/local/opt/php@7.3/include" To have launchd start @7.3 now and restart at login: brew services start php@7.3 Or, if you don't want/need a background service you can just run: php-fpm
~/.zshrcに以下を追加:
# PHP@7.3 export PATH="/usr/local/opt/php@7.3/bin:$PATH" export PATH="/usr/local/opt/php@7.3/sbin:$PATH"
有効化:
% source ./.zshrc
リンクを張る:
% brew link php@7.3
Warning: php@7.3 is keg-only and must be linked with --force
はい。
% brew link php@7.3 --force
Linking usr/local/Cellar/php@7.3/7.3.14... Error: Could not symlink sbin/php-fpm /usr/local/sbin is not writable.
/usr/localの中にsbinがない。。。
mac(HighSierra) + Laravel + Valet でつまずいたこと。。
/usr/local/sbinを使いたいがディレクトリ自体が存在しなかった。対応策を知りたい
sbinディレクトリを作るのか。。。
% sudo mkdir -p /usr/local/sbin
再度、リンクを張る:
% brew link php@7.3 --force
Linking /usr/local/Cellar/php@7.3/7.3.14... 25 symlinks created
何をやっていたかを忘れる。
pickleのインストールか。
ターミナルでpickle-masterディレクトリに戻って、再度インストールしてみる。
% composer install
確認:
% bin/pickle
██████╗ ██╗ ██████╗██╗ ██╗██╗ ███████╗ ██╔══██╗██║██╔════╝██║ ██╔╝██║ ██╔════╝ ██████╔╝██║██║ █████╔╝ ██║ █████╗ ██╔═══╝ ██║██║ ██╔═██╗ ██║ ██╔══╝ ██║ ██║╚██████╗██║ ██╗███████╗███████╗ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝ version source Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: convert Convert package.xml to new format help Displays help for a command info Display information about a PECL extension install Install a php extension list Lists commands release Package a PECL extension for release validate Validate a PECL extension
PECLのmongodb拡張は以下:
https://pecl.php.net/package/mongodb
では、インストール:
% bin/pickle install mongodb
いろいろ聞かれるが、デフォルトで。
と、エラーになった。
2: checking for libbson... configure: error: pkgconfig and libbson must be installed%
% pkg-config --version
0.29.2
なので、libbsonを入れるか。
Installing the MongoDB C Driver (libmongoc) and BSON library (libbson)
cmakeというのがいるらしい:
% brew search cmake ==> Formulae cmake ==> Casks homebrew/cask/cmake
インストールする:
% brew install cmake
Mongoc-driverをダウンロード・解凍する:
作業時の最新版は、1.16.1 。
% curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/mongo-c-driver-1.16.1.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9 100 9 0 0 27 0 --:--:-- --:--:-- --:--:-- 27
% tar xzf mongo-c-driver-1.16.1.tar.gz
tar: Error opening archive: Unrecognized archive format
いろいろアーカイバを試してみたが、解答できず。
Curlコマンドでダウンロードしたファイルが壊れていたのか、webサイト経由でダウンロードしたファイルを解凍してみたら、あっさりできた。
解凍したディレクトリに移動して、ビルドしてみる:
% mkdir cmake-build
% cmake
Build files have been written to: (絶対パスの)/cmake-build
と出たので、cmake-buildディレクトリに移動して、インストールする:
% make install
長々といろいろ吐かれるが、エラーは出なかった。
何をやっていたかを忘れる。
PECLのMongoDB拡張のインストールか。
ターミナルでpickle-masterディレクトリに戻って、再度インストールしてみる。
% bin/pickle install mongodb
いろいろ聞かれるが、デフォルトで。
と、エラーになった。
2: checking for libmongocrypt... configure: error: pkgconfig and libmongocrypt must be installed%
Libmongocryptというのがいるか。
適当にディレクトリを作って、gitリポジトリをクローンする:
% git clone https://github.com/mongodb/libmongocrypt.git
終わったら、クローンしたディレクトリに移動:
% cd libmongocrypt
makeする:
% cmake -DENABLE_SHARED_BSON=ON .
終わったら、インストールする:
% cmake --build . --target install
まあまあ長々といろいろ吐いた。
何をやっていたか忘れる。
PECLのMongoDB拡張のインストールか。
ターミナルでpickle-masterディレクトリに戻って、再度インストールしてみる。
% bin/pickle install mongodb
いろいろ聞かれるが、デフォルトで。
まあまあまあまあ長々と吐いて、何かエラーになった?
1: make install 2: mkdir: /usr/local/Cellar/php@7.3/7.3.14/pecl: File exists 2: mkdir: /usr/local/Cellar/php@7.3/7.3.14/pecl: No such file or directory 2: make: *** [install-modules] Error 1%
/usr/local/Cellar/php@7.3/7.3.14
にpeclはあるか確認:
pecl -> /usr/local/lib/php/pecl
/usr/local/lib/php
にpeclはなかった。
うーん、どうなってる。
とりあえず、
/usr/local/Cellar/php@7.3/7.3.14
のpeclのシンボリックリンクを削除して、もいっかいインストールしてみるか。
/usr/local/Cellar/php@7.3/7.3.14
に移動して、
% unlink pecl
確認:
% ls -la
→ peclはない。
ターミナルでpickle-masterディレクトリに戻って、再度インストールしてみる。
% bin/pickle install mongodb
- Installing mongodb (latest-stable): Downloading (100%) +-----------------------------------+---------+ | Package name | mongodb | | Package version (current release) | 1.7.2 | | Package status | stable | +-----------------------------------+---------+ [whether to compile against system libraries instead of bundled] (default: ): yes [whether to use system libbson] (default: ): yes [whether to use system libmongoc] (default: ): yes [whether to enable client-side encryption] (default: ): yes [whether to enable developer build flags] (default: no): no [whether to enable code coverage] (default: no): no
ここまででプロンプトが出てきたが、成功したのか?
/usr/local/Cellar/php@7.3/7.3.14
に移動してlsしてみると、peclがいる。
/usr/local/Cellar/php@7.3/7.3.14/pecl/20180731/mongodb.so
ができていた。
さて、php.iniにmongodb.soを追記してみる。
あれ、php.iniはどこにあるんだ?
% php -i | grep php.ini
Configuration File (php.ini) Path => /usr/local/etc/php/7.3 Loaded Configuration File => /usr/local/etc/php/7.3/php.ini
よし、以下を追加:
extension=mongodb.so
Apache再起動:
% sudo apachectl restart
info.phpを確認。
うん?PHP Version 7.3.11 、だと!
Homebrewでインストールしたバージョンは、7.3.14 だったな。
Apacheが使うPHPを、HomebrewであとからインストールしたPHPに変更しないとダメか。
Homebrewでインストールしたphp@7.3のlibphp7.soのパスは、
/usr/local/Cellar/php@7.3/7.3.14/lib/httpd/modules/libphp7.so
https.confのlibphp7.soの読み込み部分の記述を変更:
LoadModule php7_module libexec/apache2/libphp7.so
↓
LoadModule php7_module /usr/local/Cellar/php@7.3/7.3.14/lib/httpd/modules/libphp7.so
Apacheを再起動:
% sudo apachectl restart
再度、info.phpを確認:
PHP Version 7.3.14になった。
だがしかし、MongoDBの情報は出てこない。。。
MongoDBのモジュールが組み込まれたかどうかを確認してみる。
% php -m | grep mongo
PHP Warning: PHP Startup: Unable to load dynamic library 'mongodb.so' (tried: /usr/local/lib/php/pecl/20180731/mongodb.so (dlopen(/usr/local/lib/php/pecl/20180731/mongodb.so, 9): image not found), /usr/local/lib/php/pecl/20180731/mongodb.so.so (dlopen(/usr/local/lib/php/pecl/20180731/mongodb.so.so, 9): image not found)) in Unknown on line 0 Warning: PHP Startup: Unable to load dynamic library 'mongodb.so' (tried: /usr/local/lib/php/pecl/20180731/mongodb.so n, /usr/local/lib/php/pecl/20180731/mongodb.so.so (dlopen(/usr/local/lib/php/pecl/20180731/mongodb.so.so, 9): image not found)) in Unknown on line 0
うぅ。
Unable to load dynamic library 'mongodb.so' - Debian 8 , PHP 7.2
Extensionのディレクトリを調べてみる。
% php -i |grep extension_dir
PHP Warning: PHP Startup: Unable to load dynamic library 'mongodb.so' (tried: /usr/local/lib/php/pecl/20180731/mongodb.so (dlopen(/usr/local/lib/php/pecl/20180731/mongodb.so, 9): image not found), /usr/local/lib/php/pecl/20180731/mongodb.so.so (dlopen(/usr/local/lib/php/pecl/20180731/mongodb.so.so, 9): image not found)) in Unknown on line 0 extension_dir => /usr/local/lib/php/pecl/20180731 => /usr/local/lib/php/pecl/20180731 sqlite3.extension_dir => no value => no value
うーん、mongodb.soがインストールされたのは、
/usr/local/Cellar/php@7.3/7.3.14/pecl/20180731/mongodb.so
だったよな。
php.iniのextension_dirの設定を変更:
extension_dir = "/usr/local/lib/php/pecl/20180731"
↓
extension_dir = "/usr/local/Cellar/php@7.3/7.3.14/pecl/20180731"
確認:
% php -m | grep mongo
mongodb
お、できたか。
Apacheを再起動:
% sudo apachectl restart
再度、info.phpを確認:
MongoDBの情報が表示された。
あとはプロジェクトのディレクトリに移動して、composerでmongodbをrequireしてやると、と。
% composer require mongodb/mongodb
Using version ^1.6 for mongodb/mongodb ./composer.json has been created Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing mongodb/mongodb (1.6.0): Downloading (100%) Writing lock file Generating autoload files
やっと、アプリからMongoDBにアクセスする準備ができた。
しかし、こんなに苦労するとは。PHPでMongoDBなんて、もう誰も使わないのかね。。。