この記事は、 PHP PDOで Db2 on Cloud data warehouse (愛称 dashDB) は繋がるか? 失敗ケース の続編で、PHPの本番システムで Db2を利用できる様に、PHP 5.6.31, PHP 7.1.7 から ODBCドライバ、PDOドライバからSSL接続でアクセスが可能なことを確認しました。 使用したドライバーのパッケージは Db2の IBM Data Server Driver Package v11.1 です。 ただし、Db2には、Db2 Warehouse on Cloud(旧 DashDB), Db2 Hosted, Db2 on Cloudが含まれます。また、この検証結果は、個人の見解であり、会社の見解を代表するものではありません。
今回の目指す環境
PHPからDb2シリースのDBaaSへ接続するもので、ローカルの開発環境からインターネット越しにDb2へ接続するため、暗号化通信接続を用います。
ベース環境の起動
Macでビルド環境を作るのは、少々面倒であること、Cloud Foundry のビルドパックは、Ubuntu ベースであることから、Mac や Windows 上の Vagrant + Virtual Box の 仮想マシン上の Ubuntu 14.04 で検証を実施しました。 この仮想マシン環境を構築するために必要な Vagrantfile は、参考資料(1)にあります。 それから、MacOS や Windows 上に Vagrant の環境を未設定の場合は、参考資料(2),(3) を参照してください。 また、Gitのコマンドが入っていない場合は、Macの場合は、Xcode をインストールするか、または、参考資料(4)を参照してください。 Windows の場合も参考資料(4)に導入方法があります。
Vagrant + VritualBox の環境が出来ている方は、次のコマンドを使って、Vagrantfile をローカル環境へコピーします。
git clone https://github.com/takara9/bluemix-dev
ディレクトリを移って、仮想マシンを起動します。 このVagrantfileによって、必要なソフトウェア・モジュールを導入します。
cd bluemix-dev
vagrant up
PHP 5.6.31 のビルド
前述の Vagrantfile で立ち上がる仮想マシンに導入された phpenv と php-build を利用して、PHP 5.6.31 をビルドします。 次のコマンドを実行することで、ソースコードをダウンロードして、ビルドが始まります。 PHPのビルドには、最大で約 800MBのメモリを利用しますから、VagrantfileにはRAMを1GB取得する様に設定しています。
phpenv install 5.6.31
このビルドのソースコードは、/tmp/php-buildの下の配置されています。 odbcドライバ、pdoドライバは、このphpenvで自動的にビルドされないため、個別に設定してビルドします。
ドライバ・パッケージの導入
Db2へ接続するために必要なドライバ・パッケージを導入します。 これは Bluemix のサービスの画面からダウンロードします。 少し解りにくい場所にあるので、ダウンロードのリンクまでのアクセス手順を示します。 Db2の管理画面から次の様に、Openのホットスポットをクリックします。
次に、ドロップダウン・メニューの中から、"Connection Info"をクリックして、ダウンロードページへ移動します。
次の画面には、接続関する情報とドライバ・パッケージをダウンロードするリンクがありますから、クリックしてダウンロードします。
ダウンロードしたファイルは、ローカル環境の bluemix-dev へ移動します。 仮想マシンからは、/vagrant のディレクトリが、ホストマシンのファイル・システムになっています。 パッケージファイルを/opt/ibmの下に展開して、/opt/ibm/dsdriver のフォルダーへ移動します。 この中のインストーラーを起動して、インストールを完了させます。
vagrant@vagrant-ubuntu-trusty-64:/opt/ibm/dsdriver$ ./installDSDriver
このあと、.bash_profile に、以下の行を追加します。
# for clpplus
. /opt/ibm/dsdriver/db2profile
次のコマンドで、設定を有効にします。
exec $SHELL -l
clpplus でのログイン・テスト
clpplus が動作するためのセットアップを行います。 コマンドラインを利用する予定がなければ、このセクションは飛ばしても問題ありません。
サービス資格情報の取得
ログインするためのホスト名、ユーザーID、パスワードを取得するため、次のBluemix CLIで、ログインして、次のコマンドで、Db2のインスタンス名を取得します。
vagrant@vagrant-ubuntu-trusty-64:~$ bx cf services
Invoking 'cf services'...
Getting services in org takara9@gmail.com / space dev as takara9@gmail.com...
OK
name service plan bound apps last operation
dashDB for Analytics-iq dashDB Entry create succeeded
取得したインスタンス名に付与されているサービス資格情報の名前を取得します。
vagrant@vagrant-ubuntu-trusty-64:~$ bx cf sk "dashDB for Analytics-iq"
Invoking 'cf sk dashDB for Analytics-iq'...
Getting keys for service instance dashDB for Analytics-iq as takara9@gmail.com...
name
Credentials-1
次のコマンドで、Db2にログインするために必要な、すべての情報を入手出来ます。
bx cf service-key "dashDB for Analytics-iq" "Credentials-1"
clpplus (Db2コマンド・ライン・プロセッサ) のセットアップ
HOSTNAMEは、前述のサービス資格情報で得られたホストのドメイン名で置き換えて、実行します。
db2cli writecfg add -database BLUDB -host HOSTNAME -port 50001
次は、ラベルを設定します。 このラベルは、clpplus を実行する時に、ホスト名やポート番号と関連づけるために設定します。 dashとか短くて覚えやすいキーワードが良いと思います。
db2cli writecfg add -dsn LABEL -database BLUDB -host HOSTNAME -port 50001
さらに、SSLで接続することを指定するパラメータを追加します。
db2cli writecfg add -database BLUDB -host HOSTNAME -port 50001 -parameter "SecurityTransportMode=SSL"
これまで登録した情報を確認します。 LABELは前述で指定したもの、USERNAMEとPASSWORDは、サービス資格情報の該当項目に置き換えます。 このコマンドで、"[SUCCESS]"が表示されると、設定完了です。
db2cli validate -dsn LABEL -connect -user USERNAME -passwd 'PASSWORD'
Db2 へのログイン
以下のコマンで、ログインします。 USERNAME と LABEL は前述の db2cli validate と同じものを利用します。
clpplus -nw USERNAME@LABEL
CLPPlus: Version 1.6
Copyright (c) 2009, 2011, IBM CORPORATION. All rights reserved.
Enter password: ************
Database Connection Information :
---------------------------------
Hostname = dashdb-entry-yp-dal09-08.services.dal.bluemix.net
Database server = DB2/LINUXX8664 SQL11019
SQL authorization ID = dash10598
Local database alias = TKRDB
Port = 50001
SQL>
テストデータ作成のSQL実行
のちにPHPのプログラムの動作を確認するために、確認用データを作っておきます。 次のSQL文をsetup.sql というファイル名で作成しておきます。
DROP TABLE animals;
CREATE TABLE animals (
id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
name VARCHAR(30) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');
COMMIT;
SELECT * FROM animals;
次のコマンドで、SQL文を実行して、テーブルを作成てデータをロードします。
SQL> start ./setup.sql
これで、環境の準備が整いました。 今度は、PHPに組み込むドライバをビルドして、PHPの実行環境を設定します。
ODBCドライバのビルド
先ほど、phpenv install 5.6.31 を実行した際に、/tmp/php-build が作られ、tar形式のファイル、および、展開したフォルダーが存在しています。 このフォルダーは、/tmp の下に作られるので、再起動した後は消去されていますから、再起動後は、phpenv install 5.6.31 から再度実行しておきます。
odbc ドライバのソースコードは、/tmp/php-build/source/5.6.31/ext/odbc に展開されています。 このコードは、Db2以外のデータベースにも対応する様に書かれていますが、それ以外のコードを集めて全部入りODBCドライバーを作るのは大変なので、とりあえず、Db2専用のODBCドライバとするため、マクロ config.m4 を編集します。 編集内容は、Db2以外の部分を削除するだけなのですが、参考までに以下に添付しておきます。 それから、このマクロファイルに関して参考資料(5)にあります。
dnl
dnl $Id$
dnl
AC_DEFUN([PHP_ODBC_CHECK_HEADER],[
if ! test -f "$ODBC_INCDIR/$1"; then
AC_MSG_ERROR([ODBC header file '$ODBC_INCDIR/$1' not found!])
fi
])
dnl
dnl configure options
dnl
PHP_ARG_WITH(odbcver,,
[ --with-odbcver[=HEX] Force support for the passed ODBC version. A hex number is expected, default 0x0300.
Use the special value of 0 to prevent an explicit ODBCVER to be defined. ], 0x0300)
if test -z "$ODBC_TYPE"; then
PHP_ARG_WITH(ibm-db2,,
[ --with-ibm-db2[=DIR] Include IBM DB2 support [/home/db2inst1/sqllib]])
AC_MSG_CHECKING(for IBM DB2 support)
if test "$PHP_IBM_DB2" != "no"; then
if test "$PHP_IBM_DB2" = "yes"; then
ODBC_INCDIR=/opt/ibm/dsdriver/include
ODBC_LIBDIR=/opt/ibm/dsdriver/lib
else
ODBC_INCDIR=$PHP_IBM_DB2/include
ODBC_LIBDIR=$PHP_IBM_DB2/$PHP_LIBDIR
fi
PHP_ODBC_CHECK_HEADER(sqlcli1.h)
ODBC_INCLUDE=-I$ODBC_INCDIR
ODBC_LFLAGS=-L$ODBC_LIBDIR
ODBC_TYPE=ibm-db2
ODBC_LIBS=-ldb2
PHP_TEST_BUILD(SQLExecute, [
AC_DEFINE(HAVE_IBMDB2,1,[ ])
AC_MSG_RESULT([$ext_output])
], [
AC_MSG_RESULT(no)
AC_MSG_ERROR([
build test failed. Please check the config.log for details.
You need to source your DB2 environment before running PHP configure:
# . \$IBM_DB2/db2profile
])
], [
$ODBC_LFLAGS $ODBC_LIBS
])
else
AC_MSG_RESULT(no)
fi
fi
if test "no" != "$PHP_ODBCVER"; then
if test "$PHP_ODBCVER" != "0"; then
AC_DEFINE_UNQUOTED(ODBCVER, $PHP_ODBCVER, [ The highest supported ODBC version ])
fi
else
AC_DEFINE(ODBCVER, 0x0300, [ The highest supported ODBC version ])
fi
dnl
dnl Extension setup
dnl
if test -n "$ODBC_TYPE"; then
if test "$ODBC_TYPE" != "dbmaker"; then
PHP_EVAL_LIBLINE([$ODBC_LFLAGS $ODBC_LIBS], ODBC_SHARED_LIBADD)
if test "$ODBC_TYPE" != "birdstep" && test "$ODBC_TYPE" != "solid"; then
AC_DEFINE(HAVE_SQLDATASOURCES,1,[ ])
fi
fi
AC_DEFINE(HAVE_UODBC,1,[ ])
PHP_SUBST(ODBC_SHARED_LIBADD)
PHP_SUBST(ODBC_INCDIR)
PHP_SUBST(ODBC_LIBDIR)
PHP_SUBST_OLD(ODBC_INCLUDE)
PHP_SUBST_OLD(ODBC_LIBS)
PHP_SUBST_OLD(ODBC_LFLAGS)
PHP_SUBST_OLD(ODBC_TYPE)
PHP_NEW_EXTENSION(odbc, php_odbc.c, $ext_shared,, $ODBC_INCLUDE)
else
AC_MSG_CHECKING([for any ODBC driver support])
AC_MSG_RESULT(no)
fi
これからODBCドライバをビルドしていく前に、phpのバージョンを指定しておきます。
phpenv global 5.6.31
config.m4 の準備ができたら、次のコマンドで、configureを生成します。
phpize
configureを実行して、Makefile を生成します。
./configure
次のコマンドで、odbcドライバーをコンパイルします。
make
最後に、phpの実行環境へインストールします。
make install
簡易の確認
次のコマンドで、参照している php.ini を編集できます。 このコマンドを実行して、ODBCドライバを追加します。
php configure
次の様に行を追加します。
928 ; for on Linux
929 extension=odbc.so
930
モジュールが組み込まれるか確認するには、以下のコマンドです。 結果がodbcと表示されれば、PHP5系最新バージョンの Db2 ODBCドライバ のビルド成功です。
php -m |grep odbc
PDOドライバのビルド
次に、PDOドライバのビルドも実施します。 PDOドライバの説明は、参考資料(6)にあります。 PHPからDb2へPDOで接続するケースでは、PDOドライバは前章でビルドしたODBCドライバをラップして、PDOインタフェースを提供します。このため、Db2用のODBCドライバのビルドとインストールが前提となります。
PDO_IBMドライバは、参考資料(7)のリンクからダウンロードできます。
ダウンロードしたファイルは、Vagrant 仮想マシンとホストマシンの共用フォルダにおいて、仮想マシンの /vagrant からアクセスしてビルドします。
vagrant@vagrant-ubuntu-trusty-64:/vagrant$ pwd
/vagrant
vagrant@vagrant-ubuntu-trusty-64:/vagrant$ tar xzf PDO_IBM-1.3.4.tgz
vagrant@vagrant-ubuntu-trusty-64:/vagrant$ cd PDO_IBM-1.3.4/
今回もM4マクロを編集して、コンパイルができる様にします。 編集箇所は、2箇所で、SEARCH_PATH に /opt/ibm/dsdriver を追加、ライブラリの配置で、lib32 に誤って引きづられるので、削除してしまいます。 参考までに、以下に編集後のconfig.m4 を添付しておきます。
vagrant@vagrant-ubuntu-trusty-64:/vagrant/PDO_IBM-1.3.4$ cat config.m4
if test "$PHP_PDO" != "no"; then
PHP_ARG_WITH(pdo-ibm, for DB2 driver for PDO,
[ --with-pdo-ibm[=DIR] Include PDO DB2 support, DIR is the base
DB2 install directory, defaults to ${DB2DIR:-nothing}.
Set the PHP_PDO_IBM_LIB environment variable to set
the specific location of the DB2 libraries])
if test "$PHP_PDO_IBM" != "no"; then
DSD_PATH=/opt/ibm/dsdriver <---- 追加
SEARCH_PATH="$DSD_PATH $PHP_PDO_IBM_LIB $PHP_PDO_IBM $DB2PATH $DB2DIR" <--- 修正
AC_MSG_CHECKING(Looking for DB2 CLI libraries)
for i in $SEARCH_PATH ; do
<--- lib32,lib64 を削除 ---->
AC_MSG_CHECKING([ in $i/lib])
if test -r $i/lib/libdb2.so || test -r $i/lib/libdb2.a || test -r $i/lib/libdb400.a || test -r $i/lib/libdb2.dylib ; then
LIB_DIR="$i/lib/"
AC_MSG_RESULT(found)
break
else
AC_MSG_RESULT()
fi
done
AC_MSG_CHECKING([for DB2 CLI include files in default path])
for i in $SEARCH_PATH ; do
AC_MSG_CHECKING([in $i])
if test -r "$i/include/sqlcli1.h" ; then
PDO_IBM_DIR=$i
AC_MSG_RESULT(found in $i)
break
fi
done
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
pdo_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
pdo_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
pdo_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
AC_MSG_RESULT($pdo_inc_path)
dnl Don't forget to add additional source files here
php_pdo_ibm_sources_core="pdo_ibm.c ibm_driver.c ibm_statement.c"
PHP_ADD_INCLUDE($PDO_IBM_DIR/include)
PHP_ADD_LIBPATH($LIB_DIR, PDO_IBM_SHARED_LIBADD)
PHP_ADD_LIBRARY(db2, 1, PDO_IBM_SHARED_LIBADD)
case "$host_alias" in
*aix*)
CPPFLAGS="$CPPFLAGS -D__H_LOCALEDEF";;
esac
PHP_NEW_EXTENSION(pdo_ibm, $php_pdo_ibm_sources_core, $ext_shared,,-I$pdo_inc_path)
ifdef([PHP_ADD_EXTENSION_DEP],
[
PHP_ADD_EXTENSION_DEP(pdo_ibm, pdo)
])
PHP_SUBST(PDO_IBM_SHARED_LIBADD)
fi
fi
config.m4 の修正が完了したら、ビルドします。
phpize で configure を生成する。
vagrant@vagrant-ubuntu-trusty-64:/vagrant/PDO_IBM-1.3.4$ phpize
Configuring for:
PHP Api Version: 20160303
Zend Module Api No: 20160303
Zend Extension Api No: 320160303
configureを実行して Makefile 生成する。
vagrant@vagrant-ubuntu-trusty-64:/vagrant/PDO_IBM-1.3.4$ ./configure
コンパイルすることで、ソースから実行形式のコードを生成する。
vagrant@vagrant-ubuntu-trusty-64:/vagrant/PDO_IBM-1.3.4$ make
PHPの動的モジュールのディレクトリへコピーする。
vagrant@vagrant-ubuntu-trusty-64:/vagrant/PDO_IBM-1.3.4$ make install
こちらも、ODBCと同じ様に、phpenv configure で、 pdo_ibm.so を追加して、php -m で組み込みを確認してOKであれば終了です。
PHP ODBCでのアクセスのテスト
次のコードの ***** 部分を Bluemix から提供されるサービス資格情報で置き換えて、SSL接続でのテストができます。
1 <?php
2
3 $database = "BLUDB";
4 $hostname = "****.bluemix.net";
5 $user = "*****";
6 $password = "*****";
7 $ssl_port = 50001;
8
9 $driver = "DRIVER={IBM DB2 ODBC DRIVER};";
10
11 $ssl_dsn = "DATABASE=$database; " .
12 "HOSTNAME=$hostname;" .
13 "PORT=$ssl_port; " .
14 "PROTOCOL=TCPIP; " .
15 "SECURITY=SSL;";
16
17 $conn_string = $driver . $ssl_dsn; # SSL
18
19 #
20 $conn = odbc_connect( $conn_string,$user,$password);
21 if( $conn ){
22 echo "Connection succeeded.\n";
23
24 $sql = "SELECT id, name FROM animals";
25 $resultset = odbc_exec($conn,$sql);
26 while (odbc_fetch_row($resultset)) {
27 $id = odbc_result($resultset,"id");
28 $name = odbc_result($resultset,"name");
29 print $id." ".$name."\n";
30 }
31 odbc_close($conn);
32
33 } else {
34 echo "Connection failed.\n";
35 if (odbc_error()) {
36 echo "I've found a problem: " . odbc_errormsg($conn);
37 }
38 }
39 ?>
以下は実行結果です。 先に登録したデータがリストされているのが解ると思います。
php ./test2_odbc_ssl.php
Connection succeeded.
1 dog
2 cat
3 penguin
4 lax
5 whale
6 ostrich
PHP PDOでのアクセスのテスト
前回、PHP PDOで Db2 on Cloud data warehouse (愛称 dashDB) は繋がるか? 失敗ケースで 最新バージョンのPHPからのPDO接続を断念したのですが、ここで、もう一度トライします。 PDOインタフェース用に書き直したコードが以下になります。もちろん、SSL接続です。
1 <?php
2 $host = "*****.bluemix.net";
3 $port = 50001;
4 $dbname = "BLUDB";
5 $user = "*****";
6 $pass = "*****";
7
8 $dsn = "ibm:DRIVER={IBM DB2 ODBC DRIVER}".
9 ";DATABASE=".$dbname.
10 ";HOSTNAME=".$host.
11 ";PORT=".$port.
12 ";PROTOCOL=TCPIP".
13 ";SECURITY=SSL;";
14
15 $dbh = new PDO($dsn,$user,$pass);
16
17 foreach($dbh->query('SELECT id, name FROM animals') as $row) {
18 //print $row['id']." ".$row['name']."\n";
19 print $row[0]." ".$row[1]."\n";
20 }
21 $dbh = null;
22
23 ?>
以下は実行結果です。
php test4_pdo_ssl.php
1 dog
2 cat
3 penguin
4 lax
5 whale
6 ostrich
まとめ
PHPとPDOやODBC接続、また、SSL利用について、インターネットを検索してみたのですが、参考資料(8)〜(13)にある様な記事ばかりで、あまり参考にならない残念な記事ばかりで、相性が悪いと言った言葉で片付ける状況になっていることが解りました。 しかし、コンパイル環境を作るためのマクロを良く見直して適切なコンパイル環境を作ることで、PHPの5.6系、7系のバージョンで Db2とSSL接続するドライバをビルドできることが解りました。 次は CFコンテナにパッケージする方法を考えたいと思います。
参考資料
(1) Vagrantfile for The development environment of IBM Bluemix application https://github.com/takara9/bluemix-dev
(2) Qiita MacにVagrantとVirtualBoxを入れてみる http://qiita.com/you-me/items/3126e7f91ccdf4d8a873
(3) Qiita Windows上でVirtualBox+Vagrant+CentOSによる仮想環境構築 http://qiita.com/hiroyasu55/items/11a4c996b0c62450940f
(4) Git --distributed-is-the-new-centralized 1.5 使い始める - Gitのインストール https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
(5) PHPマニュアル UNIX 用のビルドシステム: config.m4 http://php.net/manual/ja/internals2.buildsys.configunix.php
(6) PHPマニュアル PDOドライバ http://php.net/manual/ja/pdo.drivers.php
(7) PECL PDO_IBM https://pecl.php.net/package/PDO_IBM
(8) 初めて PHP で ODBC を使ってみる https://www.ibm.com/developerworks/jp/opensource/library/os-php-odbc/index.html
(9) ODBC 64 ビット Windows および Linux に関する考慮事項 https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_61/rzaik/rzaikodbc64bitconsiderations.htm
(10) Linux または UNIX での IBM データ・サーバー製品のための PHP 環境のセットアップ https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.7.0/com.ibm.swg.im.dbclient.php.doc/doc/t0011926.html
(11) Configuring SSL for IBM Data Server Driver for ODBC and CLI https://www.ibm.com/developerworks/data/library/techarticle/dm-1512-ssl-data-server-driver-odbc-cli-trs/index.html
(12) GSKit 戻りコード https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.7.0/com.ibm.db2.luw.admin.sec.doc/doc/r0054271.html
(13) 初めて PHP で ODBC を使ってみる https://www.ibm.com/developerworks/jp/opensource/library/os-php-odbc/index.html