
Contents
PHP、MySQLとは
PHP
PHPは、Webページを動的に生成できるサーバサイドのプログラミング言語です。
DBと連携することで、SQL(Structure Query Language)を用いてWebシステムのユーザID、パスワード等の情報を取扱うことができます。
参考:PHP公式
MySQL
MySQLは、オープンソースのデータベース管理システム(DBMS)です。
DBMSは、他に以下のようなものがあります。
- Oracle Database(Oracle社)
- SQLServer(Microsoft社)
- PostgreSQL(オープンソース)
- SQLite(オープンソース)
今回は、オープンソースでかつシェアが大きく学習コストの低いMySQLについて解説します。
初めてDBを使う場合は、とりあえずMySQLから始めれば問題ありません。
参考:MySQL公式
PDOクラスとは
PHPからDBを操作する場合は、PDOクラスを使います。
PDOはPHP Data Objectの略で、PHPに標準実装されている機能です。
DB接続に関連するメソッドをたくさん備えています。
PDOクラスを使ってDBを操作する
以下に、コードの実装例を示します。
DB接続
PDOインスタンスを作成し、引数にDSN、ユーザ名、パスワードを渡してやります。
// PDOインスタンス生成
$db = new PDO(
    'mysql:host=サーバのホスト名;dbname=データベース名;charset=utf8', // DSN
    'db_user', // ユーザ名
    'db_password' // パスワード
);query文
DBのデータを操作しない場合は、query文を使います。
$stmt = $db->query('SELECT * FROM users');
echo $stmt->fetch(PDO::FETCH_ASSOC);フェッチモード
fetchやfetchAllメソッドなどでデータ取得形式としてフェッチモードがあります。
| フェッチモード | 内容 | 
|---|---|
| FETCH_BOTH | キー配列と連番の配列の双方を取得する | 
| FETCH_ASSOC | キー配列のみを取得する | 
| FETCH_KEY_PAIR | 指定した2つのデータのペアを取得する | 
| FETCH_COLUMN | 指定した1つのカラムのデータのみを取得する | 
FETCH_BOTH
キー配列と連番でデータを取得できる点で汎用的ですが、取得してくるデータが大きくなりがちです。
特に理由がない場合は、次に説明するFETCH_ASSOCを使うようにするとよいでしょう。
$stmt = $db->query('SELECT * from users');
$result = $stmt->fetch(PDO::FETCH_BOTH);
var_dump($result);
// array(8) {
//   ["id"]=>
//   int(1)
//   [0]=>
//   int(1)
//   ["name"]=>
//   string(4) "taro"
//   [1]=>
//   string(4) "taro"
//   ["email"]=>
//   string(16) "taro@example.com"
//   [2]=>
//   string(16) "taro@example.com"
//   ["password"]=>
//   string(8) "password"
//   [3]=>
//   string(8) "password"
// }FETCH_ASSOC
キー配列のみを取得します。基本的にはこのフェッチモードを使っておけば問題はありません。
$stmt = $db->query('SELECT * from users');
$result = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($result);
// array(4) {
//   ["id"]=>
//   int(1)
//   ["name"]=>
//   string(4) "taro"
//   ["email"]=>
//   string(16) "taro@example.com"
//   ["password"]=>
//   string(8) "password"
// }FETCH_KEY_PAIR
特定の2つのカラムの値のみ取得したい場合に使用します。
$stmt = $db->query('SELECT name, email from users');
$result = $stmt->fetch(PDO::FETCH_KEY_PAIR);
var_dump($result);
// array(1) {
//   ["taro"]=>
//   string(16) "taro@example.com"
// }FETCH_COLUMN
特定の1つのカラムの値のみ取得したい場合に使用します。
$stmt = $db->query('SELECT name from users');
$result = $stmt->fetch(PDO::FETCH_COLUMN);
var_dump($result);
// string(4) "taro"prepare, execute構文
INSERT文など、ユーザからのリクエストをそのままSQLの組み立てに使用するとSQLインジェクションのセキュリティリスクがあります。
$db->prepare('INSERT INTO users (name, mail) values(name, mail)');
例えば上記のような実装で、name = 'taro', mail = 'taro@example.com’); delete * from users; --'がリクエストされた場合、以下のようなSQLが組み立てられ指定したテーブルのデータが全て削除されてしまいます。
INSERT INTO users (name, mail) values('taro', 'taro@example.com');
delete from * users;
--');prepareメソッドでプリペアドステートメントを用意し、あとからexecuteメソッドで値を渡してやる必要があります。
// PDOインスタンス生成
$db = new PDO(
    'mysql:host=サーバのホスト名;dbname=データベース名;charset=utf8',
    'db_user', // ユーザ名
    'db_password' // パスワード
);
// プリペアドステートメントを生成
$db->prepare('INSERT INTO users (name, mail) value(:name, :mail)');
// クエリ実行
$db->execute([
    ':name' => 'taro',
    ':mail' => 'taro@example.com',
]);例外処理
PDOクラスを用いてDBに対してデータ操作の処理を実行する際に、処理の内容によっては失敗することがあります。
発生したエラーに対して適切な対応をするため、例外処理を用います。
PDOクラス用の例外処理クラスとしてPDOExceptionクラスが用意されているため。これを使用します。
参考:PHPリファレンス(PDOExceptionクラス)
例外処理の構文は以下の通りです。
try {
    {データ操作処理}
} catch (PDOException $e) {
    {データ操作が失敗した場合の処理}
}SQLの構文エラーが含まれているので例外処理がされ、エラーが表示されます。
try {
    $db = new PDO(
        'mysql:host=サーバのホスト名;dbname=データベース名;charset=utf8',
        'db_user', // ユーザ名
        'db_password' // パスワード
    );
    $stmt = $db->query('SELECT from users'); // SQL syntax error
    $stmt->fetch(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    echo $e->getMessage();
    // SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;
    // check the manual that corresponds to your MySQL server version for the right syntax to use near 'from users' at line 1
}トランザクション
トランザクションとは、クエリの実行内容をひとまとまりにしてDBに反映させる操作のことをいいます。
これはACID特性(Atomicity(原子性)、Consistency(一貫性)、Isolation(独立性)、Durability(永続性))を満たします。
PDOを用いたトランザクションの実装は以下のようになります。
try {
    $db = new PDO('mysql:host=ホスト名;dbname=データベース名;charset=utf8');
    $db->beginTransaction(); // トランザクション開始
} catch(PDOException $e) {
    echo $e->getMessage();
}
try {
    $stmt = $db->prepare('INSERT INTO users (name ,email) values(:name, :email)');
    $stmt->bindParam(':name' 'taro');
    $stmt->bindParam(':email', 'email');
    $stmt->execute(); // SQL仮実行
    $db->commit(); // コミット
} catch(PDOException $e) {
    $db->rollback(); // ロールバック
    echo $e->getMessage();
}beginTransactionメソッドでトランザクションを開始し、同時に反映したい複数のクエリを実行します。
クエリを実行し終わったらcommitメソッドでDBに変更を反映します。
例外を受け取った場合など、DBへの変更をもとに戻したい場合はrollbackメソッドを使います。