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メソッドを使います。