Tech

CentOSのサーバ立ててPHPからOracleに接続するまでにやったこと

LinuxでとかWindowsでとかPHPからOracleに接続する環境を構築するために、
なんかバラバラと役に立つ記事はあったけど一つにまとまった記事がなかったのでないなら作ってしまえと思い立ち、ブログを書こうと思いました。

2016年11月ごろに作った環境です。Oracleとか最新のバージョンとか出てて食い違う部分あるかもしれないですが、そこは柔軟に対応してください。
ずっと下書きで眠ってたのを公開したのでちょい古いです。

CentOSとApacheのインストールは完了している前提で話を進めます。

前提条件

  • CentOS6.8 64bit
  • Apache2.2
  • PHP5.5
  • Oracle12.1.0.2.0-1

上記のバージョンの組み合わせで構築した際のログです。
読まれてる方によって微妙に違う箇所があると思いますが柔軟に対応してください。

1.Oracle Instant Clientのインストール

Instant Client Downloads for Linux x86-64から必要なファイルを取得。

  • oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
  • oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm
    sqlplusが必要ならsqlplusも

/usr/local/src/上にダウンロードしたファイルを移動させといて、カレントディレクトリ変更

cd /usr/local/src/

インストール

rpm -ivh oracle-instantclient12.1-*.rpm

確認

rpm -qa | grep oracle

tnsnames.oraを作成 ※「HOST」、「PORT」、「SID」については、環境に合わせてください。

mkdir -p /usr/lib/oracle/12.1/client64/network/admin  
vi /usr/lib/oracle/12.1/client64/network/admin/tnsnames.ora

ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = Oracleサーバのアドレス)(PORT = 1521))
(CONNECT_DATA =
(SID = orcl)
)
)

権限の変更

chmod 644 /usr/lib/oracle/11.2/client/network/admin/tnsnames.ora

環境変数追加→/etc/profileの最後に以下4行を追加。

vi /etc/profile

export ORACLE_HOME=/usr/lib/oracle/12.1/client64/lib
export NLS_LANG=Japanese_Japan.AL32UTF8
export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH
export PATH=$ORACLE_HOME:$PATH

2.php-oci8のインストール

最初、PHPでOracleを使う為に必要な5つのことを参考に進めていた。

1.Oracle InstantClientの導入
2.php-oci8のインストール
3.環境変数の設定
4.DB名はグローバルデータベース名
5.めげない気持ち

しかし、2でどうしてもエラーが出る。。めげそう。。。

ということで基本に立ち返ってOracleのページを参考にすることに
Installing PHP and the Oracle Instant Client for Linux and Windows

PHP5.5インストール

最初、PHP5.3をyumで適当にインストールしてたので、
php5.3.3アンインストール→Remiパッケージからphp5.5をインストール(手順はphp5.5とかphp5.6をインストールするを参考にさせてもらいました。)

OCI8インストール

pecl install oci8-2.0.8

↑バージョン指定しないとPHPとの整合性でエラー出る

途中で

instantclient,/usr/lib/oracle/12.1/client64/lib

を入力します

downloading oci8-2.0.8.tgz ...
Starting to download oci8-2.0.8.tgz (190,854 bytes)
.........................................done: 190,854 bytes
11 source files, building
running: phpize
Configuring for:
PHP Api Version: 20121113
Zend Module Api No: 20121212
Zend Extension Api No: 220121212
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] :
instantclient,/usr/lib/oracle/12.1/client64/lib←途中で入力

(中略)

See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'.

running: make INSTALL_ROOT="/var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8" install
Installing shared extensions: /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8/usr/lib64/php/modules/
running: find "/var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8" | xargs ls -dils
1047547 4 drwxr-xr-x 3 root root 4096 11月 15 15:39 2016 /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8
132624 4 drwxr-xr-x 3 root root 4096 11月 15 15:39 2016 /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8/usr
132625 4 drwxr-xr-x 3 root root 4096 11月 15 15:39 2016 /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8/usr/lib64
132626 4 drwxr-xr-x 3 root root 4096 11月 15 15:39 2016 /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8/usr/lib64/php
132627 4 drwxr-xr-x 2 root root 4096 11月 15 15:39 2016 /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8/usr/lib64/php/modules
132623 492 -rwxr-xr-x 1 root root 500755 11月 15 15:39 2016 /var/tmp/pear-build-root3gXC7i/install-oci8-2.0.8/usr/lib64/php/modules/oci8.so

Build process completed successfully
Installing '/usr/lib64/php/modules/oci8.so'
install ok: channel://pecl.php.net/oci8-2.0.8
configuration option "php_ini" is not set to php.ini location
You should add "extension=oci8.so" to php.ini

その後php.iniにextension=oci8.so追加

vi /etc/php.ini

extension=oci8.so

pdo_ociインストール

ここが難関だった。。

pecl install pdo_oci

WARNING: "pear/PDO_OCI" is deprecated in favor of "channel://http://www.php.net/pdo_oci/ext/pdo_oci"
downloading PDO_OCI-1.0.tgz ...
Starting to download PDO_OCI-1.0.tgz (13,679 bytes)
.....done: 13,679 bytes
7 source files, building
running: phpize
Cannot find config.m4.
Make sure that you run '/usr/bin/phpize' in the top level source directory of the module

ERROR: `phpize' failed

普通にやったら失敗する。。。

CentOS:PHPからOracleを使えるようにするを参考にして

wget https://pecl.php.net/get/PDO_OCI-1.0.tgz  
tar xzf PDO_OCI-1.0.tgz  
cd PDO_OCI-1.0
config.m4を修正

どうやらOracle12cには対応していないようなので頑張って修正。config.m4をそのまま載せときます。
このまま動くかどうかは保証してませんので、元ファイルのバックアップを取りつつ、エラーが出たら逐次対処してください。

dnl $Id: config.m4,v 1.14.2.1 2005/09/24 23:23:24 sniper Exp $

if test "$PHP_PDO" != "no"; then

AC_DEFUN([AC_PDO_OCI_VERSION],[
  AC_MSG_CHECKING([Oracle version])
  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.11.2; then
    PDO_OCI_VERSION=11.2
  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
    PDO_OCI_VERSION=9.0
  elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.8.0; then
    PDO_OCI_VERSION=8.1
  elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.1.0; then
    PDO_OCI_VERSION=8.0
  elif test -f $PDO_OCI_DIR/lib/libclntsh.a; then
    if test -f $PDO_OCI_DIR/lib/libcore4.a; then
      PDO_OCI_VERSION=8.0
    else
      PDO_OCI_VERSION=8.1
    fi
  else
    AC_MSG_ERROR(Oracle-OCI needed libraries not found under $PDO_OCI_DIR)
  fi
  AC_MSG_RESULT($PDO_OCI_VERSION)
])                                                                                                                                                          

PHP_ARG_WITH(pdo-oci, Oracle OCI support for PDO,
[  --with-pdo-oci[=DIR]      PDO: Oracle-OCI support. Default DIR is ORACLE_HOME.
                            You may also use --with-pdo-oci=instantclient,prefix,version to use
                            the InstantClient SDK. For Linux with 10.1.0.3 rpms (for example) use:
                            --with-pdo-oci=instantclient,/usr,10.1.0.3])

if test "$PHP_PDO_OCI" != "no"; then
  AC_MSG_CHECKING([Oracle Install-Dir])
  if test "$PHP_PDO_OCI" = "yes" -o -z "$PHP_PDO_OCI"; then
    PDO_OCI_DIR=$ORACLE_HOME
  else
    PDO_OCI_DIR=$PHP_PDO_OCI
  fi
  AC_MSG_RESULT($PDO_OCI_DIR :$PHP_PDO_OCI:)

  AC_MSG_CHECKING([if that is sane])
  if test -z "$PDO_OCI_DIR"; then
    AC_MSG_ERROR([You need to tell me where to find your oracle SDK, or set ORACLE_HOME.])
  else
    AC_MSG_RESULT([yes])
  fi

  if test "instantclient" = "`echo $PDO_OCI_DIR | cut -d, -f1`" ; then
    PDO_OCI_IC_PREFIX="`echo $PDO_OCI_DIR | cut -d, -f2`"
    PDO_OCI_IC_VERS="`echo $PDO_OCI_DIR | cut -d, -f3`"
    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_VERSION="`echo $PDO_OCI_IC_VERS | cut -d. -f1-2`"
  else
    if test -d "$PDO_OCI_DIR/rdbms/public"; then
      PHP_ADD_INCLUDE($PDO_OCI_DIR/rdbms/public)
      PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/rdbms/public"
    fi
    if test -d "$PDO_OCI_DIR/rdbms/demo"; then
      PHP_ADD_INCLUDE($PDO_OCI_DIR/rdbms/demo)
      PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/rdbms/demo"
    fi
    if test -d "$PDO_OCI_DIR/network/public"; then
      PHP_ADD_INCLUDE($PDO_OCI_DIR/network/public)
      PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/network/public"
    fi
    if test -d "$PDO_OCI_DIR/plsql/public"; then
      PHP_ADD_INCLUDE($PDO_OCI_DIR/plsql/public)
      PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/plsql/public"
    fi
    if test -d "$PDO_OCI_DIR/include"; then
      PHP_ADD_INCLUDE($PDO_OCI_DIR/include)
      PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/include"
    fi

    if test -f "$PDO_OCI_DIR/lib/sysliblist"; then
      PHP_EVAL_LIBLINE(`cat $PDO_OCI_DIR/lib/sysliblist`, PDO_OCI_SYSLIB)
    elif test -f "$PDO_OCI_DIR/rdbms/lib/sysliblist"; then
      PHP_EVAL_LIBLINE(`cat $PDO_OCI_DIR/rdbms/lib/sysliblist`, PDO_OCI_SYSLIB)
    fi
    PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib"
    AC_PDO_OCI_VERSION($PDO_OCI_DIR)
  fi

  case $PDO_OCI_VERSION in
    8.0)
      PHP_ADD_LIBRARY_WITH_PATH(nlsrtl3, "", PDO_OCI_SHARED_LIBADD)
      PHP_ADD_LIBRARY_WITH_PATH(core4, "", PDO_OCI_SHARED_LIBADD)
      PHP_ADD_LIBRARY_WITH_PATH(psa, "", PDO_OCI_SHARED_LIBADD)
      PHP_ADD_LIBRARY_WITH_PATH(clntsh, $PDO_OCI_LIB_DIR, PDO_OCI_SHARED_LIBADD)
      ;;
    8.1)
      PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
      ;;
    9.0)
      PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
      ;;
    10.1)
      PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
      ;;
    11.2)
      dnl 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)
      ;;
  esac

  PHP_ADD_LIBPATH($PDO_OCI_LIB_DIR, PDO_OCI_SHARED_LIBADD)

  PHP_CHECK_LIBRARY(clntsh, OCIEnvCreate,
  [
    AC_DEFINE(HAVE_OCIENVCREATE,1,[ ])
  ], [], [
    -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
  ])

  PHP_CHECK_LIBRARY(clntsh, OCIEnvNlsCreate,
  [
    AC_DEFINE(HAVE_OCIENVNLSCREATE,1,[ ])
  ], [], [
    -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
  ])

  dnl
  dnl Check if we need to add -locijdbc8
  dnl
  PHP_CHECK_LIBRARY(clntsh, OCILobIsTemporary,
  [
    AC_DEFINE(HAVE_OCILOBISTEMPORARY,1,[ ])
  ], [
    PHP_CHECK_LIBRARY(ocijdbc8, OCILobIsTemporary,
    [
      PHP_ADD_LIBRARY(ocijdbc8, 1, PDO_OCI_SHARED_LIBADD)
      AC_DEFINE(HAVE_OCILOBISTEMPORARY,1,[ ])
    ], [], [
      -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
    ])
  ], [
    -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
  ])

  dnl
  dnl Check if we have collections
  dnl
  PHP_CHECK_LIBRARY(clntsh, OCICollAssign,
  [
    AC_DEFINE(HAVE_OCICOLLASSIGN,1,[ ])
  ], [], [
    -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
  ])

  dnl Scrollable cursors?
  PHP_CHECK_LIBRARY(clntsh, OCIStmtFetch2,
  [
     AC_DEFINE(HAVE_OCISTMTFETCH2,1,[ ])
  ], [], [
    -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
  ])

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

  PHP_SUBST_OLD(PDO_OCI_SHARED_LIBADD)
  PHP_SUBST_OLD(PDO_OCI_DIR)
  PHP_SUBST_OLD(PDO_OCI_VERSION)

  ifdef([PHP_ADD_EXTENSION_DEP],
  [
    PHP_ADD_EXTENSION_DEP(pdo_oci, pdo)
  ])

fi
fi
シンボリックリンク作成
ln -s /usr/lib/oracle/12.1/client64 /usr/lib/oracle/12.1/client  
ln -s /usr/include/oracle/12.1/client64 /usr/include/oracle/12.1/client
pdo_oci.c修正
phpize
./configure  --with-pdo-oci=instantclient,/usr,12.1
make

エラー。。。
Installing PDO_OCI and OCI8 PHP extensions on CentOS 6.4 64bitを参考

To solve it just change function_entry to zend_function_entry @pdo_oci.c file.

pdo_oci.cの
function_entryのところをzend_function_entryに変更して・・

make

通った!!!

make install

/etc/php.iniにextension=pdo_oci.soを書き込む

vi /etc/php.ini

extension=pdo_oci.so

httpdリスタート

しかし、

php -i | grep oci

でエラーが出る。。。

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/pdo_oci.so' - /usr/lib64/php/modules/pdo_oci.so: undefined symbol: php_pdo_register_driver in Unknown on line 0

どうやらダイナミックリンクライブラリの参照の順番の問題なので
pdo.ini内のextension=pdo.soをコメントアウト

vi /etc/php.d/pdo.ini

# extension=pdo.so

php.iniを編集して、pdo_oci.soの上にextension=pdo.soを追加

vi /etc/php.ini

extension=pdo.so
extension=pdo_oci.so

httpdリスタートしてエラーでないことを確認!

3.テスト

test.phpを作ってテスト

<?php
define("DB_HOST", "ホスト");
define("DB_PORT", "1521"); // デフォルト1521
define("DB_USERNAME", "ユーザ");
define("DB_PASSWORD", "パスワード");
define("DB_SID", "SID");

try {
    $dbh = new PDO("oci:dbname=//".DB_HOST.":".DB_PORT."/".DB_SID, DB_USERNAME, DB_PASSWORD);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
    die($e->getMessage());
}
echo 'OK';
exit(0);

しかし、エラー。。。

「ERROR:ORA-21561: OID生成に失敗しました」

「/etc/hosts」に自ホスト名を追加

vi /etc/hosts

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 自ホスト名を追加`

そしてついにテスト成功しました。

長くなりましたがこんな感じです。書き方こんなんでいいんかなってとこですが。

最初に見てた記事の「めげない気持ち」がほんとに重要でしたw
誰かの役に立てばいいなと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

x  Powerful Protection for WordPress, from Shield Security
このサイトは
Shield Security によって保護されています →