質問: タイトルの通りなのですが、 DBへ登録するときの方法はPDOとsqlとかっていう2種類の方法がありますよね? I.何故2種類あって、どっちを使った方がいいのでしょうか? オブジェクト型?手続き型?よくわかりませんが、 書籍の多くにはsqlでの記述が多い中 ネットでの情報の多くにはPDOでの記述の方が多いように感じられます。 私の持っている書籍にもsqlでの記述しかありません。 その為、書籍で勉強して、分からないことをいざネットで聞くと PDOとか見慣れない記述での返答が多い為、 「え?なにコレ?」ってなってしまいます。(過去の話) II.参考までに教えて頂きたいのですが、 下記サンプル記述をPDOでの記述にするとしたら どのようになるのでしょうか? III.とりあえずPDOはアロー演算子で色々指定して展開させていく、 みたいな認識なのですがこの認識で大丈夫でしょうか? また、その場合、チートシートではありませんが ->の先で使えるものの一覧のようなものはないのでしょうか? おさらいの意味も含めてIとIIとIIIについて解説お願いします。 ``` アドレス登録 登録が完了しました。戻る ```
回答: 本題に入りたいところですが,質問のコードには以下のような問題点があります. * **SQLインジェクションに対する致命的な脆弱性がある.これがある場合アプリケーションを絶対にWeb上に公開してはいけないレベル.** * **HTMLとロジックが混ざっている.HTMLを書き始める前にページ表示に必要なすべての変数を用意しておき,それが終わったらHTMLの書き出しだけに徹するべき.** * **HTMLを書いている最中に`die`で異常終了すると壊れたHTMLだけが残ってしまう.異常終了する可能性が消えるまでHTMLを書き出してはいけない.** > > タイトルの通りなのですが、 > > DBへ登録するときの方法はPDOとsqlとかっていう2種類の方法がありますよね? > > > 言葉の定義を一応はっきりさせておきます. * SQL...データベースを扱う共通言語 * MySQL...データベース製品の1つ * mysql関数群...MySQLをPHPから操作するための関数群で,PHP5.3で非推奨,PHP7.0で廃止. * mysqliクラス/mysqli関数群...MySQLをPHPから操作するためのクラス/関数群で,↑の後継. * PDOクラス...**あらゆる**データベースを共通に扱うためのクラス. > > I.何故2種類あって、どっちを使った方がいいのでしょうか? > > > どの選択肢を採用するかについてですが,まず,記述量や例外処理のしやすさを考慮すると,オブジェクト指向は避けて通れません.関数名をみてもらうと分かりますが,mysqliの手続き型は関数名からして長いため,非常に記述が冗長になります. (`mysqli_stmt_bind_param` `mysqli_stmt_get_result` とかとくに酷い例) よって,mysqliクラスかPDOクラスかの2択になります.ここは好みも分かれますが,一般的にPDOのほうが推奨される理由としては * PDO1つだけ覚えておけばすべてのデータベースに応用が効く * mysqliが多機能な一方,PDOのほうがメソッドの数や利用されるクラスの種類も少なくてシンプル といったものがあるでしょう. > > III.とりあえずPDOはアロー演算子で色々指定して展開させていく、 > > みたいな認識なのですがこの認識で大丈夫でしょうか? > > > 最初はそんな感じでいいと思います.手続き型のときの第1引数が`->`を生やされたオブジェクトになる,というイメージです.多くの場合はこの法則が成立します. > > II.参考までに教えて頂きたいのですが、 > > 下記サンプル記述をPDOでの記述にするとしたら > > どのようになるのでしょうか? > > > 指摘した問題点もすべて修正したコードを掲載します. ``` PDO::ERRMODE_EXCEPTION, // SQLのエラーに関してもPDOExceptionをスロー ]); // プリペアドステートメントを発行 $stmt = $pdo->prepare("INSERT INTO address(no, name, tel) VALUES (?, ?, ?)"); // ? の部分に値を文字列として安全にあてはめて実行 $stmt->execute([$no, $name, $tel]); } catch (PDOException $e) { // 異常があった場合ここにジャンプする // テキストとして「500 Internal Server Error」でメッセージを出して終了 header('Content-Type: text/plain; charset=UTF-8', true, 500); exit("ERROR: {$e->getMessage()}"); } // HTMLとして結果を出力 // (文字コードをここで指定すればmetaタグは省略可能) header('Content-Type: text/html; charset=UTF-8'); ?> アドレス登録 登録が完了しました。 戻る ``` 【関連記事】 * PHPでデータベースに接続するときのまとめ * $_GET, $_POSTなどを受け取る際の処理 【追記】 このコードには形式的にはCSRF脆弱性があるので,余力があればそれについても調査してみてください. (但し今回の場合はメールアドレスを登録しなければならないので,必ずしも脆弱性とは言えません.またCSRFは脆弱性の中では比較的軽微なほうです.) * 【PHP初心者向け】セキュアな掲示板を最小構成から作る * ぼくのかんがえたさいきょうのsession_start