メインコンテンツのクイズ。
とりあえず読み問題を表示させた。
理想的な出来!だけれども・・・同じ問題が何度も表示されることがある。
何故そんなことになっているのか?
いくつかの問題があることに気が付きました。
ORDER BY RAND() するときは1カラムだけ取得しなければならない
修正前は
SELECT id, question FROM questions ORDER BY RAND();で書いてしまっていたんだけれども、
複数カラム取得する場合は、それも別の行として認識されることに気が付きました。
なので、先に id だけ取得しなくてはなりません。
SELECT id FROM questions ORDER BY RAND();これを連想配列で取得すれば準備OK。
array_fill はSQLの中に入れてはならない
先ほど取得した id の配列を使って問題等の情報を取得していきます。
ただ、fetchAllで取得する際のSQL文で「?」を配列の長さ分作らなければならないのだが、
何故か「array_fill(0, count($questionIds), ‘?’))」のところで「 Uncaught ArgumentCountError: array_fill() expects exactly 3 arguments, 2 given」
というエラーになる。
SELECT * FROM questions WHERE id IN (' .
implode(',', array_fill(0, count($questionIds), '?')) .
')なんで?
完璧じゃない?
これ「’?’」が引数として認識されていないようで、
array_fillを使う場合はSQLの中に入れず、SQL外で変数に入れてから書かないといけないらしい。
正しいSQL ↓
// ここで ? を配列分あらかじめ作っておく
$placeholders = implode(
',',
array_fill(0, count($questionIds), '?')
);
$sql = 'SELECT * FROM questions
WHERE id IN (' . $placeholders . ')';やれやれ、こんなトラップがあるとは・・・
リダイレクトする場合、セッションに問題情報を保持しなくてはならない
それでも同じ問題が表示される。
どうしてかまた調べてみると・・・第1問→第2問に画面が遷移した時に、
配列に持った問題情報がまた全然違うものに変わってる?!
つまり、リダイレクトされた際に同じ処理がまた走っているので、問題IDが振り直されているということ。
これは最初(第1問)の時だけに、全ての問題情報を持たないといけない。
考えた結果、セッションで保持することにした。
// 問題セッションの初期化
if (!isset($_SESSION['quiz'])) {
$_SESSION['quiz'] = [
'current' => 1,
'questions' => [],
'answers' => [],
];
}
// 最初にアクセスされた時
if ($_SESSION['quiz']['current'] === 1) {
...
$question = (問題の配列)
// セッションに保存
$_SESSION['quiz']['question'] = $question;
}
$current = $_SESSION['quiz']['current'];
$question = $_SESSION['quiz']['question'];(冒頭)
<?php
$currentIndex = $current - 1;
$q = $question[(int)$currentIndex];
?>
...
<form method="post" action="quiz.php?action=answer" class="space-y-4">
<input type="hidden" name="question" value="<?= $q['question'] ?>">
</form>これで問題が重複して出題されることはなくなりました。
複合的な原因があると大変ですね。
