XAMPPでMySQLを使う 補遺
北本です。
今回は、XAMPPでMySQLを使う1、2、3で書いた内容の補足的なこと取り上げます。
POSTメソッドでのリクエスト送信
その2では、HTMLに以下のようにフォーム要素を配置して、GETメソッドでリクエストを送信するようにページを作成していました。
1 2 3 4 5 | <form method="GET" action="test.php"> <div>都道府県: <input type="text" name="prefecture"></div> <div>人口: <input type="text" name="population_min">以上、 <input type="text" name="population_max">以下</div> <div><input type="submit" value="送信"></div> </form> |
formのmethod属性をGETからPOSTに変更すれば、POSTメソッドでリクエストを送信できるようになります。
1 | <form method="POST" action="test.php"> |
GETメソッドの場合は、以下のような感じでURLの?以降にパラメータが付与されていましたが、POSTメソッドの場合は付与されません。
http://localhost:8080/test.php?prefecture=兵庫県&population_min=300000&population_max=500000
GETメソッドからPOSTメソッドに変更すると、PHP側も修正が必要になりますが非常に簡単です。
GETメソッドの場合$_GETという連想配列の変数からパラメータを取り出していましたが、それが$_POSTという名前の変数になるだけです。
1 2 3 | $prefecture = $_POST["prefecture"]; $population_min = $_POST["population_min"]; $population_max = $_POST["population_max"]; |
空文字列の判定
前回に完成させたPHPのコード、本筋ではないので触れていませんでしたが、実はまだ少し欠陥があります。
例えば、都道府県「兵庫県」、人口「300000」人以上、「0」人以下と入力して送信ボタンを押下します。人口が0人以下の都市はありませんし、そもそも300000人以上0人以下という大小関係がおかしいので、何もデータ取得されてほしくないところですが、結果としては兵庫県の人口300000人以上の都市が出力されます。
前回までのコードでは以下のようにemptyを使って、空値かどうかを判定していましたが、このemptyは「0」の場合でもtrueを返します。
1 | if(!empty($population_max)) |
そのため、人口の上限値(population_max)を「0」で入力した場合、未入力と同様の処理がされてしまっていたわけです。
PHPには、emptyの他にissetやis_nullが用意されており、その仕様は以下のURLなどでまとめられています。
PHP isset, empty, is_null の違い早見表
https://qiita.com/shinichi-takii/items/00aed26f96cf6bb3fe62
しかし、C#のstring.IsNullOrEmptyと同じようなものがなくて困りものです。
以下のURLでは、PHPでの空値判定関数の自作例が紹介されています。
【PHP】is_nullもissetもemptyも絶妙に微妙なので、”is_nullorempty”を自作しよう
https://qiita.com/hirossyi73/items/6e6b9b3ff155a8b05075
bindValueで疑問符プレースホルダを使う場合
前回のコードではPDOStatementのbindValueでバインドする場合、名前付きプレースホルダを使用していました。
以下は、わかりやすいように各パラメータが空値にならない前提で書き換えたものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $prefecture = $_POST["prefecture"]; $population_min = $_POST["population_min"]; $population_max = $_POST["population_max"]; $pdo = new PDO("mysql:host=127.0.0.1;dbname=testdb;charset=utf8mb4;", "root", ""); $sql = "SELECT name, prefecture, population FROM cities WHERE prefecture = :prefecture AND population >= :population_min AND population <= :population_max"; $stmt = $pdo->prepare($sql); $stmt->bindValue(":prefecture", $prefecture, PDO::PARAM_STR); $stmt->bindValue(":population_min", $population_min, PDO::PARAM_INT); $stmt->bindValue(":population_max", $population_max, PDO::PARAM_INT); $stmt->execute(); |
これを疑問符プレースホルダを使って書き換えると以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $prefecture = $_POST["prefecture"]; $population_min = $_POST["population_min"]; $population_max = $_POST["population_max"]; $pdo = new PDO("mysql:host=127.0.0.1;dbname=testdb;charset=utf8mb4;", "root", ""); $sql = "SELECT name, prefecture, population FROM cities WHERE prefecture = ? AND population >= ? AND population <= ?"; $stmt = $pdo->prepare($sql); $stmt->bindValue(1, $prefecture, PDO::PARAM_STR); $stmt->bindValue(2, $population_min, PDO::PARAM_INT); $stmt->bindValue(3, $population_max, PDO::PARAM_INT); $stmt->execute(); |
bindValueの第1引数にプレースフォルダの文字列を指定していたところが、プレースホルダの位置に応じたインデックス(1始まり)の数値になります。
ただ、前回で書いたコードのように条件によってパラメータの有無が変わる場合、疑問符プレースホルダを使おうとすると、別途変数を用意してインデックスをカウントする必要がでてくるので、名前付きプレースホルダを使った方が無難そうです。
以上で「XAMPPでMySQLを使う」シリーズは終了となります。後半はXAMPPやMySQLはほとんど関係なかったですね。PHPに関して経験0に近いところから記事を書いてきましたが一応完結させられました。
今更ながら、人口の上限が空白の場合PHP_INT_MAX、下限が空白の場合PHP_INT_MIN(負数の人口は有り得ないので0でもいいかも)を設定するようにすれば、WHERE句を条件分岐で組み立てる必要もなくなりもっとシンプルにできたかなとも思いました。後々自分で見返してみると他にもいろいろと改善の余地に気付くかもしれません。