PHPでデータベースに接続してみる


##はじめに
前提として、Vagrantでローカル環境を構築しPHPとApacheをインストールしておきます。
インストールしていない場合、下記でインストールします。

```bash
$ sudo yum install httpd
$ sudo yum install php php-cli php-common php-gd php-in tl php-mbstring php-mysql php-pdo

```

##テーブルの構造
下記のようなテーブルがあるという前提となります。

```bash
mysql> desc users;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(100) | YES  |     | NULL    |                |
| email | varchar(100) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
```


##PDOでのデータベース接続
###PDOとは
PDOは「PHP Data Objects」の略で、PHP標準（5.1.0以降）のデータベース接続クラスのことです。

###PDOでデータベースに接続する

```php
$db = new PDO('データベースの種類:host=接続先アドレス;dbname=データベース名', 'ユーザー名', 'パスワード');
```

###エラーがでた場合はPDOException（PDO が発するエラー）を投げるようにする

エラーをスローするには、``PDO->setAttribute()``でエラーの属性を設定します。 

```php
//PDO::ATTR_ERRMODE エラーレポート 
//PDO::ERRMODE_EXCEPTION exceptionsを投げる
PDO->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION) 

```

接続してみる。

```php
<?php
  define('DB_DATABASE','my_db');
  define('DB_USERNAME','my_user');
  define('DB_PASSWORD','password');
  define('PDO_DSN','mysql:host=localhost;dbname=' . DB_DATABASE);

  try{
    //DB接続
    $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
    //エラーをスロー
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  } catch(PDOException $e){
    echo $e->getMessage();
    exit;
  }
 ?>

```


##データベースへの接続を切る
データベースへの接続を切るには、PDOクラスで作成したオブジェクトをnullで置き換えるだけです。

```php
$db = null;
```


##PHPからテーブルにレコードを入れてみる

レコードを追加するには、下記のPDOオブジェクトのメソッドを使用します。

* exec()
* query()
* prepare()

###exec関数
引数に指定したコマンド（$command）を実行します。
また、コマンドの実行結果を返却しません。 

```
exec ( string $command [, array &$output [, int &$return_var ]] );
```

####実行

```php
<?php
  define('DB_DATABASE','php_test');
  define('DB_USERNAME','user');
  define('DB_PASSWORD','Sato2323');
  define('PDO_DSN','mysql:dbhost=localhost;dbname=' . DB_DATABASE);

  try{
    //DB接続
    $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //テーブルにレコードを追加
    $db -> exec("insert into users (name,email) values ('sato','sato@hogehoge.com')");

  } catch(PDOException $e){
    echo $e->getMessage();
    exit;
  }
 ?>
```


####実行結果
設定した値が挿入されているのが確認できる。

```bash
mysql> select * from users;
+----+------+-------------------+
| id | name | email             |
+----+------+-------------------+
|  1 | sato | sato@hogehoge.com |
+----+------+-------------------+
```


###prepare関数
引数に指定したコマンド（$command）に、異なるパラメータを用いて複数回実行するコマンドに適しています。
また、コマンドの実行結果を返却します。

```
prepare ( string $command [, array driver_options] );
```

####実行

```php
<?php
  define('DB_DATABASE','php_test');
  define('DB_USERNAME','user');
  define('DB_PASSWORD','Sato2323');
  define('PDO_DSN','mysql:dbhost=localhost;dbname=' . DB_DATABASE);

  try{
    //DB接続
    $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $db->prepare('insert into users (name,email) values(?,?)');
    $stmt->execute(array('sato','sato@hogehoge.com'));

  } catch(PDOException $e){
    echo $e->getMessage();
    exit;
  }
 ?>
```

``$stmt->execute(array('sato','sato@hogehoge.com'));``の箇所を、
``$stmt->execute(['sato','sato@hogehoge.com']);``と書いたら動かなかった。なぜ・・・。

追記：下記の書き方はPHP 5.3以前では動かないようです。ちなみに実行時のバージョンは5.3.3でした。
>$stmt->execute(['sato','sato@hogehoge.com']);

####実行結果
設定した値が挿入されているのが確認できる。

```bash
mysql> select * from users;
+----+------+-------------------+
| id | name | email             |
+----+------+-------------------+
|  1 | sato | sato@hogehoge.com |
+----+------+-------------------+
```

####prepare関数のパラメーターに名前を指定する

prepare関数のパラメーターに名前を指定することができます。指定の仕方は下記になります。

名前無しのパラメーター

```php
$stmt = $db->prepare('insert into users (name,email) values(?,?)');
$stmt->execute(array('sato','sato@hogehoge.com'));
```


名前付きのパラメーター

```php
$stmt = $db->prepare('insert into users (name,email) values(:name,:email)');
$stmt->execute(array('name'=>'sato','email'=>'sato@hogehoge.com'));
```

####execute()する際に、パラメーターの値をbindValueで設定する
例えば、satoという名前のユーザーに、複数のemailを設定したい場合などに、``bindValue``関数を使用すると便利らしい。。。

```
bindValue(パラメーター名もしくはindex番号,パラメータにバインドする値,データ型);
```

######実行

```php
<?php
  define('DB_DATABASE','php_test');
  define('DB_USERNAME','user');
  define('DB_PASSWORD','Sato2323');
  define('PDO_DSN','mysql:dbhost=localhost;dbname=' . DB_DATABASE);

  try{
    //DB接続
    $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $db->prepare('insert into users (name,email) values(?,?)');
    
    //名前付きパラメーターの場合
    //$stmt = $db->prepare('insert into users (name,email) values(:name,:email)');

    
    $name = 'sato';
    $stmt -> bindValue(1,$name,PDO::PARAM_STR);
    //名前付きパラメーターの場合
    //$stmt -> bindValue(':name',$name,PDO::PARAM_STR);
    
    $email = 'sato@hogehoge.com';
    $stmt -> bindValue(2,$email,PDO::PARAM_STR);
    //名前付きパラメーターの場合
    //$stmt -> bindValue(':email',$email,PDO::PARAM_STR);
    $stmt->execute();

    $email = 'sato2@hogehoge.com';
    $stmt -> bindValue(2,$email,PDO::PARAM_STR);
    $stmt->execute();

    $email = 'sato3@hogehoge.com';
    $stmt -> bindValue(2,$email,PDO::PARAM_STR);
    $stmt->execute();

  } catch(PDOException $e){
    echo $e->getMessage();
    exit;
  }
 ?>

```

######実行結果
名前を固定化して値が挿入されているのが確認できる。

```bash
mysql> select * from users;
+----+------+--------------------+
| id | name | email              |
+----+------+--------------------+
| 10 | sato | sato@hogehoge.com  |
| 11 | sato | sato2@hogehoge.com |
| 12 | sato | sato3@hogehoge.com |
+----+------+--------------------+
```

####execute()する際に、パラメーターの値をbindParamで設定する

``bindValue``は値そのものを設定するのに対して、``bindParam``は変数への参照を設定します。
``bindParam``が変数の値を参照するタイミングはexecute()が実行時です。
######実行

```php
<?php
  define('DB_DATABASE','php_test');
  define('DB_USERNAME','user');
  define('DB_PASSWORD','Sato2323');
  define('PDO_DSN','mysql:dbhost=localhost;dbname=' . DB_DATABASE);

  try{
    //DB接続
    $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $db->prepare('insert into users (name,email) values(?,?)');

    $name = 'sato';
    $stmt -> bindValue(1,$name,PDO::PARAM_STR);
    $email = 'sato@hogehoge.com';
    $stmt -> bindParam(2,$email,PDO::PARAM_STR);
    $stmt->execute();
    $email = 'sato1@hogehoge.com';
    $stmt->execute();
    $email = 'sato2@hogehoge.com';
    $stmt->execute();

  } catch(PDOException $e){
    echo $e->getMessage();
    exit;
  }
 ?>


```

######実行結果
変数を書き換えた値が、正しく反映されていることが確認できます。

```bash
mysql> select * from users;
+----+------+--------------------+
| id | name | email              |
+----+------+--------------------+
| 16 | sato | sato@hogehoge.com  |
| 17 | sato | sato1@hogehoge.com |
| 18 | sato | sato2@hogehoge.com |
+----+------+--------------------+
```

###query関数
引数に指定したコマンド（$command）に、異なるパラメータを用いて1回実行するコマンドに適しています。
また、コマンドの実行結果を返却します。


```
query ( string $command [, array driver_options] );
```

######実行

```php

<?php
  define('DB_DATABASE','php_test');
  define('DB_USERNAME','user');
  define('DB_PASSWORD','Sato2323');
  define('PDO_DSN','mysql:dbhost=localhost;dbname=' . DB_DATABASE);

  try{
    //DB接続
    $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //テーブルのレコードを抽出
    $stmt = $db->query('select * from users');
    //fetchAll(PDO::返却される配列の形式)でquery関数で返却された値を全件取得します
    $users = $stmt -> fetchAll(PDO::FETCH_ASSOC);

    foreach ($users as $user) {
      var_dump($user);
      echo
    }

  } catch(PDOException $e){
      echo 'user error';
    echo $e->getMessage();
    exit;
  }
 ?>

```

######実行結果
画面上に下記のように表示され、レコードが取得出来ているのが確認できます。

```
array(3) {
  ["id"]=>string(2) "16"
  ["name"]=>string(4) "sato"
  ["email"]=>string(17) "sato@hogehoge.com"
}
array(3) {
  ["id"]=>string(2) "17"
  ["name"]=>string(4) "sato"
  ["email"]=>string(18) "sato1@hogehoge.com"
}
array(3) {
  ["id"]=>string(2) "18"
  ["name"]=>string(4) "sato"
  ["email"]=>string(18) "sato2@hogehoge.com"
}
```

##おわり
データベースに接続して、値を設定したり、取得できたりしました。
この辺りはもっと勉強が必要そうです。