Code PHP

【PDOクラス】PHPでMySQLとDB連携する方法

2020年4月16日

悩む人
PHPを学習中でDBを用いた実装をしたいけど、DB連携の方法が分からない。
という方向けに解説します。

PHP、MySQLとは

PHP

PHPは、Webページを動的に生成できるサーバサイドのプログラミング言語です。
DBと連携することで、SQLStructure 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接続に関連するメソッドをたくさん備えています。

参考:PHPリファレンス(PHP Data Object)

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);

フェッチモード

fetchfetchAllメソッドなどでデータ取得形式としてフェッチモードがあります。

フェッチモード 内容
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メソッドを使います。

-Code, PHP

© 2024 トンボのようにまっすぐ進んでいたい Powered by AFFINGER5