データベース操作をらくらくに!
・PDOStatementクラス(公式)を呼び出す
PDOクラスの呼び出しに必要な情報
//PDOクラス呼び出し時には引数が必要です。(ここでは最低限の説明とします)
$dsn = '{ホスト};{データベース};{エンコード}';
$username = '{ユーザー}';
$password = '{パスワード}';
//呼び出し例1: 上の変数を使った例。
$dbh = new PDO($dsn, $username, $password);
//呼び出し例2: 1行で纏めてみた例。注:$dsnはスペースで区切らない。
$dbh = new PDO('mysql:host={ホスト名};dbname={データベース名};charset=utf8', '{ユーザー名}', '{パスワード}');
//エラーをスローする設定
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
・DBに接続する!
DBに接続してみる
//try catchを使う -> 接続できなければエラーメッセージを出力して終了。
try {
$dbh = new PDO('mysql:host={ホスト名};dbname={データベース名};charset=utf8', '{ユーザー名}', '{パスワード}');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit();
}
//確認
var_dump($dbh); //-> object(PDO)として確認できれば接続OK。
・PDO->executeメソッド(公式)
プリペアドステートメントを利用してストアドプロシージャをコールする!(公式)
なんのこっちゃとお思いでしょうが、サーバーリソースにやさしいDBの使い方
だと覚えてください笑
SELECT
読み込み処理
$name = $_POST['name'];
//$dbh -> 上で初期化済み&接続済みのPDOクラス。
//プリペアドステートメントの作成(SQL構文をセットしてPDOStatementの生成)
//prepareメソッド(引数: SQL構文)->(返り値: PDOStatement)
$stmt = $dbh->prepare('SELECT * FROM `users` WHERE name = ? AND height = ?');
//ストアドプロシージャをコールする(SQLの実行)
//$stmt = $stmt->execute([{?}, {?}]); -> プレースホルダの数だけ配列を引数で渡す。
//executeメソッド -> (引数: 配列)->(振る舞い: SQL構文の実行)
$stmt->execute([$name, $height]);
//ここでDBからの呼び出し結果がPDOStatementクラス内プロパティに格納されます。
//呼び出し結果を連想配列に直して出力 -> 一つずつ試してみてください。
$user = $stmt->fetch(PDO::FETCH_ASSOC); //最初の1行分だけを取り出す。-> 連想配列(1record)
$users = $stmt->fetchAll(PDO::FETCH_ASSOC); //呼び出し結果の全行を取り出す。-> 2次元配列(all record)
//注: 変数名は呼び出すテーブル名を踏襲しましょう! -> `users` -> $users
//結果の確認
var_dump($users); //若しくは$user
//配列が確認できればOK!
//プログラム内での確認: nullチェック不要
if ($user) {
//$user配列が見つかったときの処理
}
//結果の表示
//fetch -> $user: DBレコード1行分。
echo $user['id'] . ' : ';
echo $user['name'] . '<br>';
//fetchAll -> $users: DBレコードから呼び出した全行分(2次元配列)。
foreach ($users as $user) {
echo $user['id'] . ' : ';
echo $user['name'] . '<br>';
}
INSERT
インサート処理
$name = 'daisuke';
$height = '184';
$birthday '2000-03-01';
//insert set構文
$sql = 'INSERT INTO users SET name = ?, height = ?, birthday = ?';
//prepareメソッド(引数: SQL構文)->(返り値: PDOStatement)
$stmt = $dbh->prepare($sql);
//executeメソッド(引数: 配列)->(振る舞い: SQL構文の実行)
$stmt->execute([$name, $height, $birthday]);
//-> データの書き込みをphpMyAdmin等で確認してみてください。
//insert values構文 -> 個人的にはset構文のほうがわかりやすいです。
$sql = 'INSERT INTO users (name, height, birthday) VALUES (?, ?, ?)';
UPDATE
アップデート処理
$id = 20;
$name = 'ichiro';
$height = '180';
$birthday = '2000-02-02';
$sql_update = 'UPDATE users SET height = ?, birthday = ? WHERE id = ?';
//prepareメソッド(引数: SQL構文)->(返り値: PDOStatement)
$stmt = $dbh->prepare($sql_update);
//executeメソッド -> (引数: 配列)->(振る舞い: SQL構文の実行)
$stmt->execute([$height, $birthday, $id]);
//データが上書きされたかphpMyAdmin等で確認してみてください。
DELETE
デリート処理
$id = 20;
$sql_delete = 'DELETE FROM users WHERE id = ?';
//prepareメソッド(引数: SQL構文)->(返り値: PDOStatement)
$stmt = $dbh->prepare($sql_delete);
//executeメソッド -> (引数: 配列)->(振る舞い: SQL構文の実行)
$stmt->execute([$id]);
//データが削除されたかphpMyAdmin等で確認してください。
SELECTでのデータの存在確認: 例
SELECT
$sql_select = 'SELECT count(*) FROM {table名} WHERE id = ?';
$stmt = $dbh->prepare($sql_select);
$stmt->execute([$id]);
$count = (int) $stmt->fetchColumn();
if (0 < $count) {
//データが存在するときの処理
}
//データがたくさんヒットする条件の場合
//top関数は最初の1つ目を見つけたときに検索を終了する -> DB負荷が低い
$sql_select_many = 'SELECT top(1) FROM {table名} WHERE id <= ?';
SELECT以外で結果を確認して処理: 例 -> rowCount
INSERT_UPDATE_DELETE
$sql = '{insert, update, deleteいずれかのsql文}';
$stmt = $dbh->prepare($sql);
$stmt->execute([パラメータ]);
$count = $stmt->rowCount(); //-> SQL文が作用した行数を返す :int
if (0 < $count) {
//SQL文が成功したときの処理
} else {
//成功しなかったときの処理
}
//selectでも実行可能ですが公式に推奨されていません。
bindParam(公式)
bindParamの有無
//コストの違いがあります。
//サーバーの負荷を考えて使い分ければいいと思います。
$sql = 'UPDATE users SET name = ?, birthday = ?, WHERE id = ?';
$stmt = $dbh->prepare($sql);
//executeに配列で引数を与えた例 -> 型キャストが行われる -> 高コスト
$stmt->execute([$name, $birthday, $id]);
//bindParam -> 型を静的に指定 -> 低コスト
$stmt->bindParam(1, $name, PDO::PARAM_STR);
$stmt->bindParam(2, $birthday, PDO::PARAM_STR);
$stmt->bindParam(3, $id, PDO::PARAM_INT);
$stmt->execute();
・PDO->queryメソッド(公式)
queryメソッド
//プレースホルダが使えないのであまり使う場面はありません。
//引数のままSQLを実行します。
//試しに使ってみるのにいいと思います。
$sql = 'SELECT * FROM users';
$users = $dbh->query($sql);
・ショートコードでちょっとだけDBの負荷を減らす。
$stmt->execute();から直接出力する
//Traversableを実装しているためfetchAllは省略できる。
$users = $stmt->execute([$name]);
foreach ($users as $user) {
echo $user['id'] . ' : ' . $user['name'] . '<br>';
}
//上記のようにfetchAllで配列に変更しなくとも出力できます。
//-> 配列に変換する分の負荷が減ります。
//ITraversableはvar_dumpで配列の確認ができません。
//使い分けしてください。
・おまけ知識(接続、および接続の管理)
持続的な接続でキャッシュを効かせてパフォーマンスの向上
<?php
$option = [PDO::ATTR_PERSISTENT => true]; //-> コンストラクタに入れる必要あり。
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, $option);
?>
LGTMお願いします!
モチベーションがあがります!