PHPでPDOを利用してMySQL(RDS)に接続する

# はじめに
今回はPHPでPDOを利用してMySQL(RDS)に接続する手順について記載します。

この手の記事は車輪の再発明になりますが、微力ながらお役にたてれば幸いです。

今回説明用の環境としてAWSを使いました。1台のEC2(Amazon Linux)上にPHPとApacheを入れ、そこからMySQL(RDS)に接続する構成を作りました。

# EC2(Amazon Linux)の準備
PHPとApacheを稼働させるマシンを用意します。
## EC2起動
EC2を起動します。今回は無料枠の Amazon Linux(t2.micro)を選択しました。

```
$ cat /etc/system-release
$ Amazon Linux AMI release 2017.03
```

## セキュリティグループ
インバウンドで下記のプロトコルを許可します。terminal がつながって Web の表示ができるという最低限の設定ですが忘れずに設定します。

|プロトコル|ポート|
|:--|:--|
|SSH|22|
|HTTP|80|

後で使いますので Public IP を控えておきましょう。

# Webサーバ(Apache)の導入
今回はWebサーバとしてApacheをインストールします。

## リポジトリのアップデート

```
$ sudo yum update -y
```

# Apache インストール

```
$ sudo yum install -y httpd
```

## 設定変更(/etc/httpd/conf/httpd.conf)
ServerNameを"localhost"に変更します。特に必須の設定ではありませんがApacheのプロセスの起動時にエラーが出る事があります。AWSなのでIPは動的に変化しますがlocalhostの方は変わりませんのでこちらを指定しておけば問題ありません。

```
変更前）#    ServerName dummy-host.example.com
変更後）ServerName localhost
```

"index.php" が最初に表示されるようにします。特に必須ではありませんが、これで"index.php"を先に表示することができるので便利です。

```
変更前）DirectoryIndex index.html index.html.var
変更後）DirectoryIndex index.php index.html index.html.var
```

### 注意
本番運用では、他にも追加のセキュリティ設定が必要になります。"apache　セキュリティ"などで検索してみてください。

# 自動起動オン

```
$ sudo chkconfig httpd on
```

# プロセス起動

```
$ sudo service httpd start
```

# EC2からMySQL(RDS)にリモート接続できるようにする
EC2にMySQL ClientをインストールしてEC2からRDSに接続できるようにします。また説明用にテスト用のDBとテーブルを作成してデータを挿入します。

## 前提
Amazon RDS上にMySQLインスタンスが作成済であるものとします。RDSについてはこちらの投稿が参考になりました。

[Amazon RDS for MySQLインスタンス作成手順](http://qiita.com/na0AaooQ/items/7c69a88c80f1efb4cad3)

RDSのインスタンスを起動するまでは面倒ですが、一度立ててしまえばその後の使い勝手はオンプレのMySQLサーバと変わりません。AWSだから特別な作法があるというわけではありません。

## MySQL Clientをインストール
EC2にMySQL Clientをインストールします。EC2からMySQLサーバ(RDS)にリモート接続する為に必要なコマンドをインストールします。EC2にMySQLサーバをインストールしているわけではありません（念の為）。

```
$ sudo yum install -y mysql
```

## EC2からMySQL(RDS)に接続してみる
MySQLサーバにリモート接続するコマンドです。

```
$ mysql -h {エンドポイント} -u{ユーザ名} -p{パスワード}
```

ここでの"エンドポイント"は"ホスト名"と同じ意味になります。

"エンドポイント"は RDS のダッシュボード上で確認できます。例えば、"akariakazadb.c3eafafsa.ap-northeast-1.rds.amazonaws.com"というような文字列になります。"ユーザ名"と"パスワード"はインスタンス作成時に設定したものになります。仮にユーザ名が"akari"、"パスワード"がdummyなら実際こんな感じになります。

```
$ mysql -h akariakazadb.c3eafafsa.ap-northeast-1.rds.amazonaws.com -uakari -pdummy
```

繋がればプロンプトが表示されます。

```
mysql>
```

### EC2からつながらない時
セキュリティグループの設定ミスが多いようです。RDSのセキュリティグループのインバウンドで3306が許可されているか？を確認してみましょう。

## データベース作成
テスト用のデータベースを作成します。下記は例です。

データベース名：expert

```
mysql> create database expert
    -> ;
Query OK, 1 row affected (0.01 sec)
```

## テーブル作成
テスト用のテーブルを作成します。下記は例です。

テーブル名：staff

|意味|カラム名|データ型|文字数|インデックス|Auto Increment|
|:--|:--|:--|:--|:--|:--|
|番号| code | INT |-| PRIMARY |〇|
|部員| name | VARCHAR | 15 |-|-|
|パスワード| password | VARCHAR | 32 |-|-|

データベース(expert)上にテーブル(staff)を作成します。

```
mysql> use expert
Database changed
mysql>
```

```
mysql> CREATE TABLE `staff` (
    ->   `code` int AUTO_INCREMENT,
    ->   `name` varchar(15) DEFAULT NULL,
    ->   `password` varchar(32) DEFAULT NULL,
    ->   PRIMARY KEY (`code`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.11 sec)

mysql>
```

```
mysql> show tables;
+------------------+
| Tables_in_expert |
+------------------+
| staff            |
+------------------+
1 row in set (0.00 sec)

mysql>
```

# データ挿入
ダミーデータを挿入します。テスト用なので値は何でも構いません。適当に何件か追加します。

```
mysql> INSERT INTO staff (name, password) VALUES ('赤座', 'dummy');
Query OK, 1 row affected (0.00 sec)

mysql>
```

# データが登録されたことの確認

```
mysql> select * from staff;
+------+--------+----------+
| code | name   | password |
+------+--------+----------+
|    1 | 赤座   | dummy    |
|    2 | 歳納   | dummy    |
+------+--------+----------+
2 rows in set (0.00 sec)

mysql>
```

# 日本語文字化け対策
RDS でインスタンスを作成する際に UTF8 になっていないと日本語が化けることがあります。でもインスタンス作っちゃったよ！という場合、この手順で修正できます。RDS はインスタンスを一度上げると後から変更が面倒なので起動時に注意が必要です。

```
mysql> status
```

で確認すると、

```
Server characterset:    latin1
Db     characterset:    latin1
```

になっている場合、

```
mysql>  set character_set_server = utf8;
mysql>  set character_set_database = utf8;
```

を実行して、DBから作り直すと、文字化けを解消できます。

# PHP の導入
PHPをインストールして最低限の設定を行います。

## インストール

```
$ sudo yum -y install php
$ sudo yum -y install php-mysql
```
PHP のバージョンによって PDO の書き方が変わるので注意。今回 yum でインストールしたらこのバージョンでインストールされました。

```
$ php -version
PHP 5.3.29 (cli) (built: May 12 2015 22:42:19)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2014 Zend Technologies
$
```

## phpの設定
"php.ini"の一部のコメント(;)を外してパラメータも変更します。下記は変更箇所の抜粋です。

```
$ sudo vi /etc/php.ini
:
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
date.timezone = Asia/Tokyo
:
```

## Webサーバ(Apache)の再起動
"php.ini"を変更したら、設定反映のため、Webサーバ(Apache)を再起動します。文法チェックして問題なければ restart。

```
$ sudo httpd -t
Syntax OK
$ sudo service httpd restart
```

## PHP 動作確認用ページ作成

```
$ sudo sh -c "echo '<?php phpinfo();?>' >> /var/www/html/index.php"
```

## 動作確認
EC2 の Public IP をブラウザに入力して PHP の設定内容確認ページが表示されれば動作OKです。

![qiita1.png](https://qiita-image-store.s3.amazonaws.com/0/150932/a0d28647-508d-e709-db0b-c1520348b9af.png)


# PHP から MySQL(RDS) に接続
PDO で PHP から MySQL(RDS) に接続します。接続テスト用のサイトを作ります。"select * from staff;"の実行結果がブラウザ上に表示できればOKです。

## "index.php"の修正
 "index.php"を以下のように書き換えます。

```/var/www/html/index.php
<?php

try
{

$dsn='{エンドポイント}';
$user='{ユーザ名}';
$password='{パスワード}';
$dbh=new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$sql='SELECT code,name FROM staff WHERE 1';
$stmt=$dbh->prepare($sql);
$stmt->execute();

$dbh=null;

while(true)
{
        $rec=$stmt->fetch(PDO::FETCH_ASSOC);
        if($rec==false)
        {
                break;
        }
        print $rec['code'];
        print $rec['name'];

}

}
catch (Exception $e)
{
        print 'データーベース接続エラー発生';
        exit();
}

?>
```

### PDO について
こちらの投稿を参考にさせて頂きました。

[PDOで接続、SELECT、プリペアドステートメントとは（PHPでMySQLに接続）](http://qiita.com/tabo_purify/items/d1166236f3b03c7be60d)

[PDOでMySQLに接続してINSERTやUPDATEやSELECTやSUM](https://labo-iwasaki.com/code/pdo-index.html)

## 結果
![qiita2.png](https://qiita-image-store.s3.amazonaws.com/0/150932/8922414e-11e0-38d6-63d4-35ab862128c3.png)

# まとめ
AWSであるのはひとえに用意できる環境の都合でしたが、RDSもオンプレのMySQLの使い勝手と変わらないことがわかりました。

ちなみに、実際の運用では Apache のセキュリティ対策等が追加で必要になりますのでご注意ください。セキュリティについては別投稿で触れたいと思います。