LoginSignup
9
6

More than 3 years have passed since last update.

PHPでSQL: らくらくPDOクラス(初心者向け)

Last updated at Posted at 2020-09-28

データベース操作をらくらくに!

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の負荷を減らす。

Traversableインターフェース(公式)

$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お願いします!
モチベーションがあがります!

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6