課題6:生徒マイページ画面で、「月」を選択すると、その月に限定して食べられない献立を検索できるようにしたい

生徒マイページ画面では、生徒が自分が食べられない献立を一覧で確認することができます。

でも一覧だとデータが多くなってしまうので、献立を提供する「月」ごとに表示したいと思います。

そこで、マイページ画面の最上部に、「1月〜12月」から1ヶ月だけを指定できるよう、 プルダウンメニューを用意しました!

 

理想:ユーザが選択した「月」に該当する献立を一覧で表示する。

 

具体的な処理:

DBから献立をとってくる関数を用意しています。

とってくる献立の条件として、 ユーザがプルダウンから選択した月に提供する献立であることを追加します。

献立を提供する日付は、surve_date1というカラムでDATE型で保存しています。
2020-07-07みたいなデータのうち、07(月)のところだけが判定条件として使いたいです。
そのSQL自体は、以下を参考にしました。
mysqlで、datetimeのカラムの年と月だけを利用する - MogLog


参考にした結果、以下のように
WHERE句として、DATE_FORMAT関数を使って、surve_date1のうち、「月」の部分について
POST送信されて得た、ユーザが選択した月(SQLインジェクションを防ぐためにプレイスホルダー)
と一致するもの、をとってくるように記述しました!
そして、その後プレースホルダーをバインドします。

$sql = 'SELECT surve_date1, menu1 FROM menu1
    WHERE (DATE_FORMAT(surve_date1, "%m") = ":month-selected")';
$data = array(':month-selected' => $_POST['month-selected']);

ただ!これを実行しても、データは表示されません・・・。

debugで確認したところ、DBには接続できたけど、
条件に合致するデータはない、だからデータが表示されない、
ということがわかりました。

なぜ条件に合致するデータがないのか?!
たとえば、

$sql = 'SELECT surve_date1, menu1 FROM menu1
    WHERE (DATE_FORMAT(surve_date1, "%m") = 07)';

ってすると、7月に提供される献立が一覧表示されるのに・・・。

原因:
調査中

2020年8月14日追記
調査したこと

$stmt->debugDumpParams()

を行って、クエリ文の確認と使用したパラメーターに関する情報(数、名前、型など)を得ました。
https://www.php.net/manual/ja/pdostatement.debugdumpparams.php

SQL: [153] SELECT surve_date1, menu1 FROM menu1 WHERE (DATE_FORMAT(surve_date1, "%m") = ":month-selected") ORDER BY surve_date1 ASC Params: 1 Key: Name: [15] :month-selected paramno=-1 name=[15] ":month_selected" is_param=1 param_type=2

その結果、期待されるクエリ文できちんと通っていること、:month-selectedがパラメーターとして渡されていることを確認しました。
ただ、きちんとバインドされているかどうかは分かりません・・・。

ちなみに、

$sql = 'SELECT surve_date1, menu1 FROM menu1
    WHERE  EXISTS (SELECT food1 FROM student WHERE
        id = :id AND food1 = menu1.menu1_allergin1';
        $data = array(':id' => $_SESSION['user_id']);

に対して、debugDumpParamsを行うと、

SELECT food1 FROM student WHERE id = '14' AND food1 = menu1.menu1_allergin1 

というように、プレイスホルダーがバインドされてクエリ文が表示されるのはなんで?
やっぱり、月指定をしたSQLにはなにか問題があるんでしょう・・・。



②月指定をしたSQLにはプレイスホルダーを:month-selectedとしていますが、
プレイスホルダーに、ハイフンを使ってはいけないことを知りました。
PHPでデータベースに接続するときのまとめ - Qiita

そのため、以下の記述に修正しました。

$sql = 'SELECT surve_date1, menu1 FROM menu1
    WHERE (DATE_FORMAT(surve_date1, "%m") = ":month_selected")';
$data = array(':month-selected' => $_POST['month_selected']);

SQL結果は変わりなし



③またHTMLで月を指定するためのプルダウンの記述が、以下のようになっていました。

<select name="month-selected">
    <option>選択してください</option>
    <?php $month = array(1,2,3,4,5,6,7,8,9,10,11,12);
    foreach ($month as $key){ ;?>
    <option value="<?php echo $key; ?>"
      <?php if(isset($_SESSION['month-selected']) && $_SESSION['month-selected'] == $key) echo "selected"; ?>>
      <?php echo $key; ?>
    </option>
    <?php
        };
    ?>
</select>
<option value="<?php echo $key; ?>

このvalueに、プルダウンで選択された数字(この時点では正しくは数値だが、DBに接続してSQLを通す時、異なる型を比較する場合自動で型が変換される)が入ります。
つまり、このvalueに入った数字=:month_selected=$_POST['month-selected']ということです。

しかし、このままの記述では、1桁の数字が選択された場合、例えば8月が選択された場合、
以下のコード内WHERE句に代入して考えてみると、

$sql = 'SELECT surve_date1, menu1 FROM menu1
    WHERE (DATE_FORMAT(surve_date1, "%m") = ":month-selected")';
$data = array(':month-selected' => $_POST['month-selected']);

WHERE (DATE_FORMAT(surve_date1, "08") = "8")'; となり、08と8は違うからデータが一致しないのかもしれません!

と思い、HTMLを以下のように修正しました。

<option value="<?php printf("%02d", $key); ?>"

これによって、選択された数字が1桁だった場合、0が足されるようになります。
SQL結果は変わりなし