hello foo bar Saba note | PHP7でOracleに接続する

PHP7でOracleに接続する

2018.10.23 (火)

oci_connect()はデフォルトのPHPには含まれていない関数なのでoci8とpdo_ociのインストールが必要です。

  • Instant Client18.3
  • oci8
  • pdo_oci

オラクルクライアント(Instant Client)のインストール

まずは普通にコマンドラインからつながるようにしておきます。どっちにしろ開発で使うので。
Oracle Instant Client
mysqlとかだったら特にクライアントとか意識せずにClientとRemoteの両方のマシンにmysqlをインストールしてしまえばいいんですが、Oracleは面倒です。まずはOracle Instant Clientでsqlplusでもってコマンド上でログインして操作できるようにしてみます。
Instant Clientのダウンロード
バージョンを確認すると、

oracle-instantclient18.3-sqlplus-18.3.0.0.0-1.x86_64.rpm
oracle-instantclient18.3-sqlplus-18.3.0.0.0-1.x86_64.rpm
oracle-instantclient18.3-devel-18.3.0.0.0-1.x86_64.rpm

が使えそうです。

$ rpm -ivh oracle-instantclient18.3-sqlplus-18.3.0.0.0-1.x86_64.rpm
$ rpm -ivh oracle-instantclient18.3-sqlplus-18.3.0.0.0-1.x86_64.rpm
$ rpm -ivh oracle-instantclient18.3-devel-18.3.0.0.0-1.x86_64.rpm

各アプリケーションがOracleライブラリを自動でロードできるようにしておきます。
ユーザーごとにパスを通さなくてもよし。

echo "/usr/lib/oracle/18.3/client64/lib" > /etc/ld.so.conf.d/oracle-instant-client.conf
[root@side1 oracle_client] $ cat /etc/ld.so.conf.d/oracle-instant-client.conf

このコマンドで有効化

$ ldconfig

以下のコマンドで対話型のsqlplus64が起動できたら成功。

$ sqlplus64

SQL*Plus: Release 18.0.0.0.0 - Production on Wed Oct 24 21:19:48 2018
Version 18.3.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.

これで一応オラクルのinstantclientが使えるようになっている。
とはいえ以下2つの変数は設定しないと駄目みたいです。設定されていれば表示されます。設定されていなかったら設定する。

$ export ORACLE_SID=orcl
$ echo $ORACLE_SID

サービス名もないと叱られたので設定しておく。

$ export SERVICE_NAME=example
$ echo $SERVICE_NAME

これで接続できるようになっている。

$ sqlplus64 user/password@host:1521/servicename

ログインできたらオラクルのSQL文がいろいろ使えます。
(※)ちなみに環境変数にORACLE_SIDとかSERVICE_NAMEが設定されていなくてもつながるときあるんですよね。どうしてだろ。

PHP7から接続できるようにする

oci8

PHPエクステンションのoci8が必要です。

yum install --enablerepo=remi-php72 php-oci8.x86_64
(yum install php-oci8 ??)

確認

$ php -i | grep oci8

/etc/php.d/20-oci8.ini,
oci8
oci8.connection_class => no value => no value
oci8.default_prefetch => 100 => 100
oci8.events => Off => Off
oci8.max_persistent => -1 => -1
oci8.old_oci_close_semantics => Off => Off
oci8.persistent_timeout => -1 => -1
oci8.ping_interval => 60 => 60
oci8.privileged_connect => Off => Off
oci8.statement_cache_size => 20 => 20

ドライバーの確認

$ php -i | grep driver
または
$ php -r 'var_dump(PDO::getAvailableDrivers());'

PDO_OCIの確認

php -i | grep PDO_OCI

私の環境ではmysql,oci,sqliteが登録されていました。phpinfo()でブラウザー側かも確認してみたほうがよいです。問題なければApacheの再起動行います。

$ systemctl restart httpd.service

PHPで適当なコードを書いてテスト

$dbhost = "host.example.com";
$dbport = "1521";
$dbname = "orcl.example.com";
$dsn  = 'oci:dbname='.$dbhost.':'.$dbport.'/'.$dbname;
$user = 'user';
$pass = 'password';

try {
  $dbh = new PDO($dsn, $user, $pass);
  var_dump($dbh);
  echo "OK";
} catch (PDOException $e) {
  echo $e->getMessage()."\n";
}

オブジェクトが取得できればOK。

Laravel5から接続できるようにする

必要なパッケージはこれ。
Packagist: yajra/laravel-oci8
Github: yajra/laravel-oci8

$ php composer.phar require yajra/laravel-oci8:v5.7.2

require-devにも追加しておいた方がいいかもです。
インストールが成功したら準備完了です。
詳しくはこちら

おまけ

データ取得の際に日本語が文字化けしたら、

SELECT VALUE FROM NLS_DATABASE_PARAMETERS 
WHERE PARAMETER='NLS_CHARACTERSET';

で設定されている文字コードを調べます。そして以下のように文字コードを指定してあげます。

...
$dsn  = 'oci:dbname='.$dbhost.':'.$dbport.'/'.$dbname.';charset=AL32UTF8';
...

参考

yumで入れたPHPにoci8とpdo_ociを入れる
[PHP, OCI8] yum経由でphp-oci8をインストールした場合のoracleクライアント系soの置き場
PHPマニュアル oci_connect
Linuxからsqlplusを利用してOracleに接続する
PDO_OCI のインストール(CentOS7対応)
amazon linux に sqlplus をインストール
oracle sqlplusでつなごうと思ったらORA-12162: TNS:net service name is incorrectly specifiedというエラーが出た。
PHP7 OracelDBクライアントインストール(PDO, OCI8)