jiichan.com

PROGRAMMING

PDOでデータベース操作

PHPでのデータベース操作にはさまざまなライブラリがあります。
数ある中で、複数のデータベースに対応している(データベースが変更されてもメンテナンスしやすい)などの理由でPDOを選択しました。
PDOはPHP5.1からの標準機能であり特に追加インストールなどは必要ありません。

データベース処理の流れ

データベース処理の流れは概ね次のようになります。

1. データベースに接続 2. データの参照(抽出)・データの更新(追加、変更、削除) 3. データベース接続を閉じる
最後の接続解除は、明示的に記述しなくてもスクリプト終了で接続は解除されます。

データベースに接続

最初の流れとしてデータベースへの接続があります。
PDO基底クラスのインスタンスを作成することにより、接続が確立されます。 コンストラクタにデータソース・ユーザー名・パスワードの引数を渡します。
下の例はMySQLへの接続の場合です。


$dsn = "mysql:dbname=test;host=localhost;charset=utf8;"; // データソース
$conn = new PDO($dsn, $username, $password); // 接続

1行目のデータソースの最後にcharset=utf8;が記述されていますが、文字コードを明示的にPDOに渡すことで文字化けを防ぐことができます。 これはPHP5.3.6以降追加されました。それまでは接続後に$conn->query("SET NAMES utf8");というふうにクエリを発行していました。

データの抽出

データベース処理の中では一番多く使われる処理だと思います。表示までの流れとしては

1. SQL文を準備 2. SQL文にパラメータがある場合はパラメータをバインド 3. 準備したSQL文を実行 4. 返されたデータを1行ずつ処理して表示
のようになります。
これをプリペアドステートメントを使用した例で示します。


// 1.SQL文を準備(プリペアドステートメントの準備)
$sql = "SELECT name, age, sex FROM member WHERE sex = ?";
$stmt = $conn->prepare($sql);

// 2.パラメータ(プレースホルダー?)があったのでバインド
$stmt->bindParam(1, $sex); // 1番目(1個しかないので)のパラメータに$sexを括りつけ
$sex = "女";

// 3.SQL文を実行(プリペアドステートメントの実行)
$stmt->execute();

// 4.fetch()で一行ずつ$rowに取り出して処理
while ($row = $stmt->fetch()) {
	echo $row[0]."/".$row[1]."/".$row[2]."<br>";
}

プリペアドステートメントはSQL文のパラメータを除いた部分を事前にコンパイルしておきます。そのためクエリの解析が必要なのは最初の一回だけです。 したがって、別のパラメータを指定しても高速にクエリを実行することができることになります。
また、プリペアドステートメントに渡すパラメータ(プレースホルダーを利用)は、引用符で括る必要がないため、SQLインジェクションの心配もありません。

参照系のqueryメソッドや更新系のexecメソッドの利用もできますが、このような理由からプリペアドステートメントを利用して処理を行うほうが良いと思います。

13行目のfetch()には引数として定数を指定できます。定数には ・ PDO::FETCH_ASSOC(カラム名で添字を付けた配列を返す) ・ PDO::FETCH_BOTH(カラム名と0で始まるカラム番号で添字を付けた配列を返す) などがあります。
上の例のように引数なしの場合はデフォルト値であるPDO::FETCH_BOTHが指定されたことになります。

カラム名の場合は$row['name']、0で始まるカラム番号の場合は$row[0]ようにアクセスすることになります。
なお、プレースホルダーには疑問符プレースホルダー「?」のほかに「:sex」のように「:」で始まる名前つきプレースホルダーも使用できます。

データの更新

データの更新には、データの追加・データの変更・データの削除とありますが、それらはSQL文の違いだけなので例としてデータの追加のみを取り上げます。


$sql = "INSERT INTO member(team, name, age, sex) VALUES (?, ?, ?, ?)";
$stmt = $conn->prepare($sql);

$stmt->bindParam(1, $team);
$stmt->bindParam(2, $name);
$stmt->bindParam(3, $age);
$stmt->bindParam(4, $sex);

// 行を挿入します
$team = 'A';
$name = '東田';
$age = 46;
$sex = '男';
$stmt->execute();

// パラメータを変更し、別の行を挿入します
$team = 'B';
$name = '西谷';
$age = 65;
$sex = '女';
$stmt->execute();

bindParamメソッドを使わずにexecuteに直接、パラメータを配列として渡す方法もあります。


$sql = "INSERT INTO member(team, name, age, sex) VALUES (?, ?, ?, ?)";
$stmt = $conn->prepare($sql);

// 行を挿入します
$stmt->execute(array('A', '東田', 46, '男'));

// パラメータを変更し、別の行を挿入します
$stmt->execute(array('B', '西谷', 656, '女'));

コード量が少なく、簡単で見やすく良いですね。

データベース接続を閉じる

スクリプトが終了した時点で自動的に接続は閉じられますが、明示的に接続を閉じる場合は次のようにPDOオブジェクトにnullを代入します。


$conn = null;

PHPのデータベース操作にはやはりPDOが良いかと思います。