七十歳からの独習
オブジェクト指向 Work-2-2 PDOクラスでデータを取得(SELECT)prepare版
【ワークの目標】
MariaDB(MySQL)とPHPを使って、WEB上で動く仮想の販売管理システムを作ること。もちろん完成すればわが農園でも応用できる。
前回はqueryメソッドを使って、PDOクラスでデータを取得(SELECT)の操作したが、よりセキュリティ対策が可能なprepareメソッドを使ってデータベースの操作をしてみよう。

店舗テーブル(tenpo)
店舗コード | 店舗名 | |
カラム名 | tenpo_code | tenpo_name |
属性 | varchar | varchar |
長さ | 4 | 20 |
インデックス | UNIQUE | UNIQUE |

queryは手続きが簡素で、prepareは手続きが少し複雑なようだ。
ならば、使いやすいqueryに行きたいところで、実は私もこれまでは、queryを使ってきた。しかし、いろいろ勉強してみると、わざわざ手続きを複雑にしているには理由がある訳で、「SQLインジェクション攻撃」対策としてはprepareを使った方が安全なようだ。
と言うことで、sample2-1.phpを改良してみる。
まず、新しい用語「プレースホルダ」を理解する。
Prepareメソッドを使うためには、SQL文のSQL部分と値の部分を明確に分けることにより安全性を確保する。値を入れる部分にプレースホルダを置く。
プレースホルダには2種類ある。
:名前形式と?形式の2つがある。下のサンプルの10行目の:tenpo_codeがプレースホルダ、:名前形式を採用している。
【PDOクラスでデータを取得(SELECT)】sample2-2 prepareメソッドを使用
- <?php
- // 変数の初期化
- $search_key = '%0002%';
- try {
- // DBへ接続
- $dbh = new PDO("mysql:host=localhost; dbname=sms; charset=utf8", 'root', 'password');
- // SQL作成
- $sql = "SELECT * FROM tenpo where tenpo_code like :tenpo_code";
- // SQL実行準備
- $res = $dbh->prepare($sql);
- //値をバインド
- $res->bindValue(':tenpo_code', $search_key,PDO::PARAM_STR);
- // SQL実行
- $res->execute();
- // 取得したデータを出力
- foreach( $res as $value ) {
- echo "$value[tenpo_code]:$value[tenpo_name]<br>";
- }
- }
- //エラー処理
- catch(PDOException $e) {
- echo $e->getMessage();
- die();
- }
- // 接続を閉じる
- $dbh = null;
- ?>
【注意】
4行目の
$dbh = new PDO(“mysql:host=localhost; dbname=sms; charset=utf8″, ‘root’, ”);
は、セキュリティ上の理由でソース内に記述すべきではない。
PHPのソースは外部からは基本的には見えないが、何らかの原因で見られてしまう可能性も否定できない。外部から見られたくない部分はhtdocsフォルダ外に記述し、sample1-3.phpで記述した方法で読み込むようにする。
もちろん、ログイン名とパスワードも適正に設定する。
【実行結果】
0002:飯野支店
3行目の$search_key = ‘%0002%’;は0002を含む検索を行うためだ。
10行目でSQL文を書くが値の部分は値を直接記述せず、プレースホルダを記述する。tenpo_code like :tenpo_codeのように演算子はlikeを使う。
3行目を$search_key = ‘0002’;とすれば、10行目はtenpo_code = :tenpo_codeの様に演算子は=を使う。
13行目で、SQL文をプリペアし、16行目で、プレースホルダに値をバインドする。
16行目のPDO::PARAM_STRはデータ型を示す。店舗コードは文字なので、このように明示する。これによりSQLインジェクションに対する安全性を高める。
データ型にはいくつかあるようだが、主なものを掲載する。詳しくはPHPの公式ドキュメントを参照してほしい。
しかし、少数や日付のときはどうするのか? 該当するデータ型がない。どうも、PDO::PARAM_STRを使えば良いらしい。
定数 | 説明 |
PDO::PARAM_INT | SQL INTEGER データ(整数)型を表す。 |
PDO::PARAM_STR | SQL CHAR, VARCHAR, または他の文字列データ型を表す。 |
これで、一番簡単なSELECTは終了。次はINSERTを学習する。