Azure Web Apps 環境の PHP で DB 接続文字列のハンドリング

#概要
　Azure Web Apps の代表的な構成は **Web + DB** となります。実際 Azure ポータルから Web App をデプロイする際には、以下のように Web App と様々な Azure PaaS Database を組み合わせた一括デプロイが提供されています。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/3e970d06-d2eb-58d3-d131-cf6775f02c0f.png)

　いずれの組み合わせでも Web App から DB へセキュアに接続するには、WEB アプリケーションのコード中に ID やパスワードを埋め込まず環境変数（接続文字列）から取得するのが一般的となります。本記事では参考例の多くない PHP + SQL Database を使ったサンプルを提示しています。

#接続文字列と環境変数
　Web App + SQL のデプロイをすると、既定で下記の２つの環境設定項目 **[アプリケーション設定]** と **[接続文字列]** が設定されます。何れも環境変数として登録されますが [接続文字列] は ID パスワードを含むセキュアな情報という事でポータルでの初期表示は非表示に設定されています。
　![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/01470621-d0a6-2327-bf18-1ca14db4c17f.png)

　またプログラムからアクセスする場合、[接続文字列] は Database の種類によって固定された Prefix を伴うネーミング規則が使用されます。

| Database タイプ | Prefix 文字列     |
|:---------------|:-----------------|
| SQLAzure       | SQLAZURECONNSTR_ |
| SQLServer      | SQLCONNSTR_      |
| MySql          | MYSQLCONNSTR_    |
| Custom         | CUSTOMCONNSTR_   |

　例えば SQL Database (SQLAzure) の場合、defaultConnection と定義された接続文字列は **SQLAZURECONNSTR_defaultConnection** として WEB アプリケーションからアクセスする必要があります。以下に PHP のサンプルコード例を掲載します。

```php:getenv.php
<?php
	// アプリケーション設定を環境変数より取得
	$appsetting = getenv("WEBSITE_NODE_DEFAULT_VERSION");
	echo $appsetting

	// 接続文字列を環境変数より取得
	$connstr = getenv("SQLAZURECONNSTR_defaultConnection");
	echo $connstr
?>
```
#PHP から SQL Database へ接続
　SQL Database 既定の接続文字列は、以下のようなフォーマットとなっています。

```config:接続文字列（defaultConnection）
Data Source=tcp:db1.database.windows.net,1433;Initial Catalog=db1;User Id=user@db1.database.windows.net;Password=hoge;
```
　この既定の接続文字列から正規表現で各要素を取り出しているのが、下記 PHP コード例となります。接続文字列自体をカンマ区切りでシンプルに定義し直したり、ID パスワードだけを接続文字列に格納する等してプログラムからの取り出しを簡潔にする方法もあります。

```php:dbconnect.php
<?php
	// 接続文字列を環境変数より取得
	$connstr  = getenv("SQLAZURECONNSTR_defaultConnection");
	
    // 接続文字列を各要素へ分解
    foreach ($_SERVER as $key => $value) 
    {
        if (strpos($key, "SQLAZURECONNSTR_") !== 0) 
        {
            continue;
        }
        $hostname = preg_replace("/^.*Data Source=(.+?);.*$/", "\\1", $value);
        $database = preg_replace("/^.*Initial Catalog=(.+?);.*$/", "\\1", $value);
        $username = preg_replace("/^.*User Id=(.+?);.*$/", "\\1", $value);
        $password = preg_replace("/^.*Password=(.+?);.*$/", "\\1", $value);
        break;
    }

	$connectionOptions = array(
	    "Database" => $database,
	    "Uid" => $username,
	    "PWD" => $password
	);

	// データベースへ接続
	$conn = sqlsrv_connect($hostname, $connectionOptions);
	$sql= "SELECT * FROM [dbo].[test_table]";
	$getResults= sqlsrv_query($conn, $sql);
	echo ("<p>Reading data from SQL Database.</p>" . PHP_EOL);
	
	// テーブルからデータ取得
	if ($getResults == FALSE)
		echo (sqlsrv_errors());
	while ($row = sqlsrv_fetch_array($getResults, SQLSRV_FETCH_ASSOC)) {
		echo ($row['ID'] . " " . $row['Name'] . " " . $row['Value'] . "<br>" . PHP_EOL);
	}
	
	// 解放処理
	sqlsrv_free_stmt($getResults);
?>
```

　参考：SQL Database の DB は、以下の T-SQL で作成しています。

```sql:createtable.sql
CREATE TABLE test_table (
  ID int,
  Name nvarchar(10),
  Value int
)

INSERT INTO test_table VALUES ( 1, 'NAME1', 10 )
INSERT INTO test_table VALUES ( 2, 'NAME2', 20 )
INSERT INTO test_table VALUES ( 3, 'NAME3', 30 )
INSERT INTO test_table VALUES ( 4, 'NAME4', 40 )
INSERT INTO test_table VALUES ( 5, 'NAME5', 50 )
```