トップ 一覧 置換 検索 ヘルプ RSS ログイン

PHPでOracleへ接続するの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!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_fetch_arrayで取得すると、ファイルポインタが返ってくる。
!OCI-Lob クラスとして扱う
oci_fetch_arrayで取得すると、OCI-Lob クラスが返ってくる。

{{category2 プログラミング言語,PHP}}