!!!PDO を使う !!仕組み PDO -> PDO_OCI -> Oracleライブラリ !!準備 !必要なもの 11g は失敗するかも *Oracle Instant Client basic 10g *Oracle Instant Client devel 10g *php-pdo{{ref PDO_OCI-1.0.tgz}} *re2c {{ref re2c-0.13.5-1.el5.rf.i386.rpm}} [dag] name=Dag RPM Repository for Red Hat Enterprise Linux baseurl=http://ftp.riken.jp/Linux/dag/redhat/el$releasever/en/$basearch/dag gpgcheck=1 gpgkey=http://ftp.riken.jp/Linux/dag/packages/RPM-GPG-KEY.dag.txt yum install re2c !インストール + Oracle Client をインストール + PDO_OCI をインストール({{goto install_pdo_oci, PDO_OCIインストールを参照}}) + /etc/php.d/pdo_oci.ini を作成し、extension=pdo_oci.so を追加 !!接続 define ("_dns","oci:dbname=192.168.10.139/xe"); define ("_db_user",'test'); define ("_db_pass",'test'); db = new PDO(_dns,_db_user,_db_pass); な感じ !!注意点 !日付のデフォルトフォーマット 自分が想定している日付のフォーマットになっていないことがある。 alter session set NLS_DATE_FORMAT = 'yyyy/mm/dd hh24:mi みたいな感じで日付のフォーマットを決めておいたほうが良い。 !!!MDB2 を使う !!仕組み MDB2 -> MDB2_Driver_oci8 -> oci8 -> Oracleライブラリ !!準備 !必要なもの *Oracle Instant Client basic 10g *Oracle Instant Client devel 10g 11g は失敗するかも !インストール + Oracle Client をインストール + oci8 をインストール ({{goto install_oci8, oci8インストールを参照}}) + pear install MDB2 + pear install MDB2_Driver_oci8 + php.ini または、 /etc/php.d/oci8.iniを作成し、extension=oci8.so を追加 !!接続 define ("_dns","oci8://test:test@//192.168.10.139/xe"); db = MDB2::factory( _dns ); な感じ。または、 oci8://test:test@192.168.10.139:1521/?service=xe {{word ==注意==,red}} ==10g の場合== == test:test@//192.168.10.139:1521/xe== ==のようにポート指定をすると接続に失敗するので注意== !!!各ライブラリのインストール方法 {{anchor install_oci8}} !!oci8 インストール !peclを使う場合 pecl install oci8 を実行。 Please provide the path to the ORACLE_HOME directory. Use 'instantclient,/path/to/instant/client/lib' if you're compiling with Oracle Instant Client [autodetect] : と出たらOracle instant のライブラリのパスを入力する。 入力例: instantclient,/usr/lib/oracle/10.2.0.4/client/lib/ instantclient,/usr/lib/oracle/10.2.0.4/client64/lib/ !peclを使わない場合 peclに存在しない等の理由でエラーが出る場合は手動でインストールする。 http://pecl.php.net/package/oci8 から {{ref oci8-2.0.8.tgz}}をダウンロード。 tar zxvf oci8-2.0.8.tgz cd oci8-2.0.8 phpize ./configure --with-oci8=instantclient,/usr/lib/oracle/10.2.0.4/client64/lib/ <= パスは環境にあわせて修正 make make install {{anchor install_pdo_oci}} !!PDO_OCIインストール !10g ※ 64bit 版は client64 にインストールするが PDO_OCI の configure スクリプトは client 決め打ちなのでディレクトリー名を変更する ※ configure スクリプトの方を変更しても良い・・・かも。 + 64bitの場合、/usr/lib/oracle/バージョン/client64 を /usr/lib/oracle/バージョン/client へシンボリックリンクを貼るか、リネームす + 64bitの場合、/usr/include/oracle/バージョン/client64 を /usr/include/oracle/バージョン/client へシンボリックリンクを貼るか、リネームする + wget http://pecl.php.net/get/PDO_OCI-1.0.tgz + tar xvfz PDO_OCI-1.0.tgz + cd PDO_OCI-1.0 + phpize + データベース(SJIS) - クライアント(UTF-8)の場合ソースを修正する ++ -col->maxlen = data_size; ++ +col->maxlen = data_size*3; + ./configure --with-pdo-oci=instantclient,/usr,10.2.0.4 <- Oracle Client のバージョン + make + make install !12c http://www.code-knight.com/suzuking/items/75fad3dacfc7a8b0b7535d68359d554a 以下パッチファイルを作成 patch.txt ### Eclipse Workspace Patch 1.0 #P pdo_oci Index: config.m4 =================================================================== --- config.m4 (revision 141) +++ config.m4 (working copy) @@ -7,6 +7,8 @@ if test -s "$PDO_OCI_DIR/orainst/unix.rgs"; then PDO_OCI_VERSION=`grep '"ocommon"' $PDO_OCI_DIR/orainst/unix.rgs | sed 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4` test -z "$PDO_OCI_VERSION" && PDO_OCI_VERSION=7.3 + elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.12.1; then + PDO_OCI_VERSION=12.1 elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then PDO_OCI_VERSION=10.1 elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.9.0; then @@ -57,14 +59,19 @@ AC_MSG_CHECKING([for oci.h]) if test -f $PDO_OCI_IC_PREFIX/include/oracle/$PDO_OCI_IC_VERS/client/oci.h ; then PHP_ADD_INCLUDE($PDO_OCI_IC_PREFIX/include/oracle/$PDO_OCI_IC_VERS/client) + PDO_OCI_LIB_DIR="$PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/lib" AC_MSG_RESULT($PDO_OCI_IC_PREFIX/include/oracle/$PDO_OCI_IC_VERS/client) elif test -f $PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/include/oci.h ; then PHP_ADD_INCLUDE($PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/include) + PDO_OCI_LIB_DIR="$PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/lib" AC_MSG_RESULT($PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/include) + elif test -f $PDO_OCI_IC_PREFIX/sdk/include/oci.h ; then + PHP_ADD_INCLUDE($PDO_OCI_IC_PREFIX/sdk/include) + AC_MSG_RESULT($PDO_OCI_IC_PREFIX/sdk/include) + PDO_OCI_LIB_DIR="$PDO_OCI_IC_PREFIX" else AC_MSG_ERROR([I'm too dumb to figure out where the include dir is in your instant client install]) fi - PDO_OCI_LIB_DIR="$PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/lib" PDO_OCI_VERSION="`echo $PDO_OCI_IC_VERS | cut -d. -f1-2`" else if test -d "$PDO_OCI_DIR/rdbms/public"; then @@ -119,6 +126,9 @@ 10.2) PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD) ;; + 12.1) + dnl PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD) + ;; *) AC_MSG_ERROR(Unsupported Oracle version! $PDO_OCI_VERSION) ;; @@ -176,22 +186,24 @@ -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD ]) - ifdef([PHP_CHECK_PDO_INCLUDES], - [ - PHP_CHECK_PDO_INCLUDES - ],[ - AC_MSG_CHECKING([for PDO includes]) - if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then +dnl ifdef([PHP_CHECK_PDO_INCLUDES], +dnl [ +dnl PHP_CHECK_PDO_INCLUDES +dnl ],[ + AC_MSG_CHECKING([ PDO includes]) + if test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then + pdo_inc_path=$prefix/include/php/ext + elif test -f $prefix/include/php5/ext/pdo/php_pdo_driver.h; then + pdo_inc_path=$prefix/include/php5/ext + elif 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 ]) PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared,,-I$pdo_inc_path) ※ 64bit 版は client64 にインストールするが PDO_OCI の configure スクリプトは client 決め打ちなのでディレクトリー名を変更する ※ configure スクリプトの方を変更しても良い・・・かも。 + 64bitの場合、/usr/lib/oracle/12.1/client64 を /usr/lib/oracle/12.1/client へシンボリックリンクを貼るか、リネームす + 64bitの場合、/usr/include/oracle/12.1/client64 を /usr/include/oracle/12.1/client へシンボリックリンクを貼るか、リネームする + wget http://pecl.php.net/get/PDO_OCI-1.0.tgz + tar xvfz PDO_OCI-1.0.tgz + cd PDO_OCI-1.0 + patch -p0 < patch.txt + phpize + データベース(SJIS) - クライアント(UTF-8)の場合ソースを修正する ++ -col->maxlen = data_size; ++ +col->maxlen = data_size*3; + ./configure --with-pdo-oci=instantclient,/usr,12.1 <- Oracle Client のバージョン + make + make install !!!文字コード DBサーバとクライアントの文字コードが異なる場合は以下のいずれかの方法で設定する。 !!接続時に文字コードを指定する charset を指定する。 例 oci:dbname=IP/ORCL;charset=AL32UTF8 oci8://test:test@192.168.10.139:1521/?service=xe&charset=AL32UTF8 !!環境変数等に文字コードを指定する NLS_LANG=Japanese_Japan.UTF8 等の環境変数を設定する !!!ORA-24408 が発生する場合 /etc/hosts に 127.0.0.1 自分のホスト名 を書く。自分のホスト名からIPが引けないとこのエラーが出てしまうことがあるみたい。 !!!LOBの扱い !!MDB2 大きく2つの方法がある。 !文字列として扱う 特に意識しなければ、普通のvarchar2と同じように扱える。 ただし、末尾のスペースが消えるなどの動作することがあるので注意。 !ファイルポインタとして扱う prepareの第3引数に戻り値の型を渡すことでblobの戻り値をファイルポインタが返ってくる。 $db->loadModule('Datatype'); .... $sql = "select ....." $types = null; null か バインド変数の型 $returnTypes = array("blob", "text"); $st = db->prepare($sql, $types, $returnTypes); $rows = $st->fetchAll(MDB2_FETCHMODE_ASSOC); $res = $rows[0]["img"]; if (is_resource($res)) { while(!feof($res)) { echo fread($res, 8192); ob_flush(); flush(); } } $db->datatype->destroyLOB($res); !!OCI8直接 MDB2同様、大きく2つの使い方がる。 !文字列として扱う oci_fetch_allで取得すると文字列として取得できる。MDB2の時のように末尾のスペースが消えることはない。 !OCI-Lob クラスとして扱う oci_fetch_arrayで取得すると、OCI-Lob クラスが返ってくる。 {{category2 プログラミング言語,PHP}}