備忘録: PDO と SQL 文
はじめに
研究で Android 端末から SQL サーバにアクセスしてデータを見るというアプリを作っています。実は今までアプリケーションを作成することがなかった(学部時代はデータ分析をしていたので元データのパース用スクリプト程度しか書いていなかった)ので、いきなり Android Java (と PHP )の勉強を強いられる事になった上、納期が3週間後(5月末)に設定されるという地獄の状況です。今現在の話です。
で、そのアプリはサーバとのデータのやり取りを PHP への POST で実現していて、端末から文字列をバイトデータとして PHP に送って、その文字列を SQL クエリの WHERE としてテーブルを抽出する、という処理を書くことになりました。そこで詰まったのでメモ。
ダメなやつ
[Android]
// 前略 URL url = new url ("http://hogehoge/.../hoge.php") HTTPURLConnection con = (HTTPURLConnection)url.openConnection(); con.setReqestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); // 接続 con.connect(); OutputStream out = new BufferedOutputStream (con.getOutputStream()); out.write("Hoge".getBytes("UTF-8")); out.flush; // 後略
[PHP]
<?php // 前略 $data = file_get_contents ('php://input'); $stmt = $dbh -> prepare ("SELECT * FROM table_hoge WHERE hoge_id =".$data); $stmt.execute(); // table_hoge の hoge_id は nvarchar(30) // 後略 ?>
何がまずかったか
PHP の2行目。PDO (PHP Data Objects) の prepare は引数として String を持つから、 PHP の記法上、普通はシングルクォーテーションで括るべきなのにダブルクォーテーションにしてしまっています。それから文字列と変数 $data をドットで連結しているのも問題。一応これでも動くことは動くんですが、空のデータしか返ってきません。
どうしてこうなったか
- いろんなインターネット上の情報を寄せ集めてパッチのごとく設計したことの弊害
- 実は検索対象のデータ型が int だと特に問題なかった
同様の処理を int 型の要素に対して行っていたので、それをちょこっと変えただけで適用したのがまずかったです。考えてみれば当たり前なんだけど。
修正版
[PHP]
// 前略 $data = file_get_contents ('php://input'); $stmt = $dbh -> prepare ('SELECT * FROM table_hoge WHERE hoge_id = :data'); $stmt.execute(array(':data' => $data)); // table_hoge の hoge_id は nvarchar(30)
prepare 内の文字列をシングルクォーテーションに変更。
execute() のタイミングで入力文字列を渡すように変更。
おわりに
PHP やってる人からしたら初歩の初歩なんだろうなぁ……。これで午前中潰してしまったのが悔やまれる。
他の人へ参考に、というよりは自分の戒めとして記事作成しました。