何度も同じ問題が表示される問題に立ち向かう

メインコンテンツのクイズ。

とりあえず読み問題を表示させた。

理想的な出来!だけれども・・・同じ問題が何度も表示されることがある。

何故そんなことになっているのか?

いくつかの問題があることに気が付きました。

目次

ORDER BY RAND() するときは1カラムだけ取得しなければならない

修正前は

SQL
SELECT id, question FROM questions ORDER BY RAND();

で書いてしまっていたんだけれども、

複数カラム取得する場合は、それも別の行として認識されることに気が付きました。

なので、先に id だけ取得しなくてはなりません。

SQL
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」

というエラーになる。

SQL
SELECT * FROM questions WHERE id IN (' .
  implode(',', array_fill(0, count($questionIds), '?')) .
  ')

なんで?

完璧じゃない?

これ「’?’」が引数として認識されていないようで、

array_fillを使う場合はSQLの中に入れず、SQL外で変数に入れてから書かないといけないらしい。

正しいSQL ↓

PHP
  // ここで ? を配列分あらかじめ作っておく
  $placeholders = implode(
      ',',
      array_fill(0, count($questionIds), '?')
  );

  $sql = 'SELECT * FROM questions
          WHERE id IN (' . $placeholders . ')';

やれやれ、こんなトラップがあるとは・・・

リダイレクトする場合、セッションに問題情報を保持しなくてはならない

それでも同じ問題が表示される。

どうしてかまた調べてみると・・・第1問→第2問に画面が遷移した時に、

配列に持った問題情報がまた全然違うものに変わってる?!

つまり、リダイレクトされた際に同じ処理がまた走っているので、問題IDが振り直されているということ。

これは最初(第1問)の時だけに、全ての問題情報を持たないといけない。

考えた結果、セッションで保持することにした。

PHP(Controller)
  // 問題セッションの初期化
  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'];
HTML(View)
(冒頭)
<?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>

これで問題が重複して出題されることはなくなりました。

複合的な原因があると大変ですね。

  • URLをコピーしました!
目次