setup IIS + PHP + Oracle 

#Outline
今回、windows server上でOracleに接続するWEBアプリを作る機会がありました。
Oracleに接続するにあたり、多少設定などに苦労したことがあるため、自分の構築メモふくめて、手順を残しておく


# Environment

| Item  | Version | Memo |
|:-----------|------------:|:------------:|
| OS       | Windows Server 2019 Standard|          |
| DB       | Oracle 12.1.0.2.0|          |
| PHP | 7.4.14 (32bit) |          |
| Instant Client |19.8.0.0.0 |          |

# Instant Client

### Download

ここから、Basicパッケージをdownloadする

https://www.oracle.com/jp/topics/technologies/download-instant-client.html

なお、bit数(x86=32bit)は後述するPHPのbit数と合わせる必要がある

今回、Microsoft Windows 32ビット用　19.8.0.0.0　を使用した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/a516c65d-3f49-3c2a-49c8-9e3ce64dfada.png)

### Setup

zipを解凍後、<B>C:\instantclient</B>に配置した

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/bffb60ad-f02d-e911-7037-cab11009ea06.png)


# PHP setup

### Download

https://www.php.net/downloads.php

ここから、環境等に合わせて、phpをdownloadする
今回、stable、performanceを考慮して、<B>VC15 x86 Non Thread Safe (2021-Jan-05 18:10:14)</B>を使用した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/e6e58f5a-58e0-d566-790b-f24304039421.png)



### set file

zipファイルを解凍し、任意のパスに置く
今回は <B>"C:\php"</B>に配置した

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/9911803e-7bfc-a596-5744-dd2fedd9cf08.png)

### iniの設定

php.ini-development　もしくは php.ini-productionを php.iniに変更orコピーする
IIS環境が、開発向けか公開向けかによってどっちのtemplateを使用するか決める。
今回、社内向けツールのため、DEBUGのしやすさを考慮してphp.ini-developmentを用いた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/40348c7b-8ec3-b010-6ef0-ab61f639e526.png)

php.iniを開き、必要個所を編集する

### extensionのpathの設定

extension_dir がdefaultコメントアウトされている。
こちらを有効にし、適切なパスを設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/94d3a84a-c0d6-3c59-f48a-8ab727c85613.png)

### oracle系のextension

oci8_12c , pdo_oci が oci_connection等、oracle DBに接続するためのextension
こちらを、有効にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/2e216095-1dc6-df4e-f845-003d7f87f178.png)


### Instant Client dll 配置

先ほど設定した、instant clientの<B>C:\instantclient</B> 配下にある、dllを<B>"C:\php"</B>以下にコピーする


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/19b0e6ad-3203-3378-f834-a935af23a486.png)

その後、extensionが正しく稼働するかをコマンドで確認する。
<B>oci8</B> , <B>PDO_OCI</B>がmodule listに表示され、かつエラーが表示されないことを確認する。
ただしくdllが読み込まれないと、エラーが表示される


```
php.exe -m
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/fe2c89db-d0bd-0746-aeda-f8a6dc8de798.png)





# IIS setup

### Add Role in Server Manager

Server Managerを起動し、"Add roles and features" を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/d823091e-56a1-641f-718b-6ff532e046ba.png)

Server Rolesにて、Web Server(IIS)を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/aa317dc6-ae7f-98bb-5145-b81b3dcdbe35.png)


Role Servicesにて、CGIを少なくとも追加する。
それ以外に、ASP等必要に応じて追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/860951af-56c0-cf5b-3ae9-8d6e473028e1.png)


### Configration

IIS Managerを起動する
対象のserverを選択し、"Handler Mapping"を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/1efc419c-977f-e3cc-51ca-61745ce24fee.png)

Add Module Mappingを選択し、PHPの定義を追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/913c09e5-e6dd-469b-bb16-d2430b2c9dca.png)

※ Module にてFastCgiModuleが表示されない場合、Server Roleの Role Servicesで CGIを追加していない可能性がある。改めて、Server Roleの設定を見直す必要がある


PHP 動作確認
下記、phpinfo.phpを作成し、IISのroot directoryに配置する (Default <B>C:\inetpub\wwwroot</B>)
そして、アクセスして確認する

```
<?php
phpinfo();
?>
```

http://localhost/phpinfo.php

動作確認例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/eacb4f7e-6a09-9fed-d116-0eff892daea2.png)


# Oracle 接続サンプルphp

今回、tnsnames.oraを直接phpに記載した例。

oracleの環境によって$ORAの必要項目はことなるため、カスタマイズする必要がある。
今回、SERVER、INSTANCE_NAMEに関して設定が不要のため、コメントアウトしている。


```
<?php

	$dbhost = "oracle-host";
	$dbport = "1521";
	$dbname = "dbname";

	$user = 'USER-NAME';
	$pass = 'PASSWORD';

	$ORA = "(DESCRIPTION= "
         ." (ADDRESS=(PROTOCOL=tcp)(HOST=$dbhost)(PORT=$dbport)) "
         ."  (CONNECT_DATA= "
         ." (SERVICE_NAME=$dbname) "
//         ." (SERVER=server) "
//         ." (INSTANCE_NAME=instance_name)"
         ." )) "
         ;

	$conn = oci_connect($user, $pass, $ORA );

	if (!$conn) {
	    $e = oci_error();
	    trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
	}

	$stid = oci_parse($conn, "SELECT * FROM XXX WHERE ID = '12345' ");
	oci_execute($stid);


	echo "<table border='1'>\n";
	while ($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
	    echo "<tr>\n";
	    foreach ($row as $item) {
	        echo "    <td>" . ($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;") . "</td>\n";
	    }
	    echo "</tr>\n";
	}
	echo "</table>\n";

?>
```