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 ... 

とか何とか。

 

PHP7にMongoDBをインストールする  

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でMongoDB(実践編)

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がオワコンという情報もあり、どうしたものかね。

 

PHP7.4ではPEARがインストールされなくなる  

と、調べていると、peclの代替でpickleというのがあるそうで、これを使ってみますか。

 

 

pickle - PHP Extension installer  

pickleはcomposerというのを使ってインストールするらしいので、まずはcomposerをインストールしてみる。

 

 

macOSに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って何だ?

 

install ext-zip for Mac

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をダウンロード・解凍する: 

http://mongoc.org/ 

作業時の最新版は、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 

いろいろアーカイバを試してみたが、解答できず。

 

tar xzvfの不具合  

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というのがいるか。 

 

 

mongodb/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 だったな。

 

Mac内蔵のApacheのPHPのバージョンを変更する  

 

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なんて、もう誰も使わないのかね。。。