1

All関連するドロップダウンメニューの一方または両方でオプションを選択するときに、データをループするのに問題があります。すべてのレコードを調べて表示するのではなく、1セットのデータを通過するだけです。各生徒と参加した各質問の詳細を表示することを想定しています。ただし、表示されているのは1人の生徒と1つの質問だけであり、それだけです。

表示される内容は次のとおりです。

ここに画像の説明を入力してください

しかし、代わりに、現時点ではこれを表示しているだけです。

ここに画像の説明を入力してください

この問題の原因は、私が設定した動的なWHERE句であると思います。以下は、動的WHERE句のしくみです。

  • 強制的なWHERE条件q.SessionId = ?
  • ユーザーが学生のドロップダウンメニューから1人の学生を選択した場合は、AND sa.StudentId = ?WHERE句に追加します
  • ユーザーが All学生のドロップダウンメニューから学生のオプションを選択した場合はAND sa.StudentId = ?、WHERE句から削除するか表示しない
  • ユーザーが質問のドロップダウンメニューから単一の質問を選択した場合は、AND q.QuestionId = ?WHERE句に追加します
  • ユーザーが All質問ドロップダウンメニューから質問オプションを選択した場合はAND q.QuestionId = ?、WHERE句から削除するか表示しない

私は3つのドロップダウンメニューを持っています(以下はサンプルデータでどのように見えるかです):

セッション:

<select name="session" id="sessionsDrop">
<option value="26">POKUB1</option>
<option value="27">POKUB2</option>
</select>

学生:

<select name="student" id="studentsDrop">
<option value="0">All</option>
<option value="39">Luke Mcfadzen</option>
<option value="40">Chris Tucker</option>
</select>

質問:

<select name="question" id="questionsDrop">
<option value="0">All</option>
<option value="72">1</option>
<option value="73">2</option>
</select>

この質問で前述したWHERE条件がどのように機能するかを忘れないでください。セッションドロップダウンメニューから選択されたセッションがであるとしましょうPOKUB 1, drop down value: 26

1人の生徒と1つの質問を選択すると、詳細が正しく表示されます。

  • 学生: Luke McFadzen-ドロップダウン値:39
  • 質問: 1-ドロップダウン値:72

したがって、WHERE条件はq.SessionId = 26 AND sa.StudentId = 39 AND q.QuestionId = 72です。

しかし、All学生と質問のドロップダウンメニューのいずれかまたは両方でオプションを選択すると、出力には1人の学生と1つの質問のみが表示され、奇妙な理由で、すべての質問からの回答が結合され、すべての学生の回答が1つの出力に結合されます。

両方Allのドロップダウンメニューのオプションのドロップダウン値は00データベースから選択する値ではありませんが、動的where句で0、特定のドロップダウンメニューから値を選択した場合は、から関連する条件を削除することを示しました。 WHERE句。たとえば、次のようになります。

  • All学生と単一の質問(値72)-WHERE q.SessionId = 26 AND q.QuestionId = 72
  • 単一(値39)の学生とAll質問-WHERE q.SessionId = 26 AND sa.StudentId = 39
  • All学生とAll質問-WHERE q.SessionId = 26

上記のシナリオには問題があります

静的なWHERE句をクエリに残した場合、学生と質問WHERE q.SessionId = ?を選択すると詳細が正しく出力されますが、ドロップダウンメニューから選択したすべての異なるオプションに対してクエリが機能する必要があるため、動的なWHEREが必要な理由句。正しい詳細が出力されるようにするにはどうすればよいですか?AllAll

コード:

    $selectedstudentanswerqry = "
        SELECT
        sa.StudentId, StudentAlias, StudentForename, StudentSurname, q.SessionId, 
        q.QuestionId, QuestionNo, QuestionContent, o.OptionType, q.NoofAnswers, 
        GROUP_CONCAT( DISTINCT Answer ORDER BY Answer SEPARATOR ',' ) AS Answer, r.ReplyType, QuestionMarks, 
        GROUP_CONCAT(DISTINCT StudentAnswer ORDER BY StudentAnswer SEPARATOR ',') AS StudentAnswer, ResponseTime, MouseClick, 
        (
        SELECT sum( StudentMark )
        FROM Student_Answer sta
        WHERE sa.StudentId = sta.StudentId
        AND sa.QuestionId = sta.QuestionId
        )StudentMark
        FROM Student st
        INNER JOIN Student_Answer sa ON (st.StudentId = sa.StudentId)
        INNER JOIN Student_Response sr ON (sa.StudentId = sr.StudentId) AND sa.QuestionId = sr.QuestionId
        INNER JOIN Question q ON (sa.QuestionId = q.QuestionId)
        INNER JOIN Answer an ON q.QuestionId = an.QuestionId
        LEFT JOIN Reply r ON q.ReplyId = r.ReplyId
        LEFT JOIN Option_Table o ON q.OptionId = o.OptionId
        ";

        // Initially empty
        $where = array('q.SessionId = ?');
        $parameters = array($_POST["session"]);
        $parameterTypes = 'i';


        //check if POST is empty

        // Check whether a specific student was selected
        $p_student = empty($_POST["student"])?'':$_POST["student"];

        switch($p_student){
        case 0:
            //dont' add where filters
            break;
        default:
            $where[] = 'sa.StudentId = ?';
            $parameters[] .= $_POST["student"];
            $parameterTypes .= 'i';
        }

        // Check whether a specific question was selected
        $p_question = empty($_POST["question"])?'':$_POST["question"];

        switch($p_question){
        case 0:
            //dont' add where filters
            break;
        default:
            $where[] = 'q.QuestionId = ?';
            $parameters[] .= $_POST["question"];
            $parameterTypes .= 'i';
        }

        // If we added to $where in any of the conditionals, we need a WHERE clause in
        // our query
        if(!empty($where)) {
            $selectedstudentanswerqry .= ' WHERE ' . implode(' AND ', $where);
            global $mysqli;
            $selectedstudentanswerstmt=$mysqli->prepare($selectedstudentanswerqry);
            // You only need to call bind_param once

            if (count($where) == 1) {
            $selectedstudentanswerstmt->bind_param($parameterTypes, $parameters[0]);
        }
        else if (count($where) == 2) {
            $selectedstudentanswerstmt->bind_param($parameterTypes, $parameters[0], $parameters[1]);
        }
        else if (count($where) == 3) {
            $selectedstudentanswerstmt->bind_param($parameterTypes, $parameters[0], $parameters[1], $parameters[2]);
        }

        }

        $selectedstudentanswerqry .= "
          GROUP BY sa.StudentId, q.QuestionId
          ORDER BY StudentAlias, q.SessionId, QuestionNo
        ";

    // get result and assign variables (prefix with db)
    $selectedstudentanswerstmt->execute(); 
    $selectedstudentanswerstmt->bind_result($detailsStudentId,$detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname,$detailsSessionId,
    $detailsQuestionId,$detailsQuestionNo,$detailsQuestionContent,$detailsOptionType,$detailsNoofAnswers,$detailsAnswer,$detailsReplyType,$detailsQuestionMarks,
    $detailsStudentAnswer,$detailsResponseTime,$detailsMouseClick,$detailsStudentMark); 

    $selectedstudentanswerstmt->store_result();
    $selectedstudentanswernum = $selectedstudentanswerstmt->num_rows(); 

 while ($selectedstudentanswerstmt->fetch()) {

                //Check if the student data exist.
                if (!isset($questions[$detailsStudentId])) {
                    $questions[$detailsStudentId] = array(
                        'studentalias' => $detailsStudentAlias,
                        'studentforename' => $detailsStudentForename,
                        'studentsurname' => $detailsStudentSurname,
                        'questions' => array()
                    );
                }

                $questions[$detailsStudentId]['questions'][$detailsQuestionId] = array(
                    'questionno'=>$detailsQuestionNo,
                    'content'=>$detailsQuestionContent,
                    'optiontype'=>$detailsOptionType,
                    'noofanswers'=>$detailsNoofAnswers,
                    'answer'=>$detailsAnswer,
                    'replytype'=>$detailsReplyType,
                    'questionmarks'=>$detailsQuestionMarks,
                    'studentanswer'=>$detailsStudentAnswer,
                    'responsetime'=>$detailsResponseTime,
                    'mouseclick'=>$detailsMouseClick,
                    'studentmark'=>$detailsStudentMark
                );
            }

            $selectedstudentanswerstmt->close();

    foreach ($questions as $studentId => $studentData) {
        echo '<p>'.$studentData['studentalias'].' - '.$studentData['studentforename'].' '.$studentData['studentsurname'].'</p>';

        foreach ($studentData['questions'] as $questionId => $questionData) {
            echo '<p><strong>'.$questionData['questionno'].': '.$questionData['content'].'<br/>';
            echo $questionData['optiontype'].' - '.$questionData['noofanswers'].' - '.$questionData['answer'].' - '.$questionData['replytype'].' - '.$questionData['questionmarks'].'<br/>';
            echo $questionData['studentanswer'].' - '.$questionData['responsetime'].' - '.$questionData['mouseclick'].' - '.$questionData['studentmark'].'</strong></p>';
        }
    }

以下は、$_POST['student']およびの可能なvar_dumps$_POST['question']です。

単一の学生と単一の質問:

  • 学生:クリス・タッカー-string(2) "40"
  • 質問:1-string(2) "72"

一人の学生とすべての質問:

  • 学生:クリス・タッカー-string(2) "40"
  • 質問:すべて-string(1) "0"

すべての学生と単一の質問:

  • 学生:すべて-string(1) "0"
  • 質問:1-string(1) "72"

すべての学生とすべての質問:

  • 学生:すべて-string(1) "0"
  • 質問:すべて-string(1) "0"

以下は、生徒と質問var_dump($questions);を選択した場合の例です。AllAll

array(1) { 
[39]=> array(4) { 
["studentalias"]=> string(8) "u4838229" 
["studentforename"]=> string(5) "Chris" 
["studentsurname"]=> string(6) "Tucker" 
["questions"]=> array(1) { 
[72]=> array(11) { 
["questionno"]=> int(1) 
["content"]=> string(14) "What is a RAM?" 
["optiontype"]=> string(3) "A-E" 
["noofanswers"]=> int(1) 
["answer"]=> string(7) "B,C,D,E" 
["replytype"]=> string(6) "Single" 
["questionmarks"]=> int(5) 
["studentanswer"]=> string(9) "A,B,C,D,E" 
["responsetime"]=> string(8) "00:00:07" 
["mouseclick"]=> int(1) 
["studentmark"]=> string(1) "2" } } } }

アップデート:

チェックするq.SessionId = ?だけのときに静的WHERE句を使用してmysqliクエリを保持する場合、etiherまたは両方のドロップダウンメニューでオプションを選択すると、All問題なく結果が出力されます。必要な動的where句のみが枯渇します。Allオプションが正しく機能しない個々の学生および/または個々の質問を選択できることをユーザーとして含めます。以下は、静的WHERE句を使用する場合のmysqliコードの動作です。

$selectedstudentanswerqry = "
    SELECT
    sa.StudentId, StudentAlias, StudentForename, StudentSurname, q.SessionId, 
    q.QuestionId, QuestionNo, QuestionContent, o.OptionType, q.NoofAnswers, 
    GROUP_CONCAT( DISTINCT Answer ORDER BY Answer SEPARATOR ',' ) AS Answer, r.ReplyType, QuestionMarks, 
    GROUP_CONCAT(DISTINCT StudentAnswer ORDER BY StudentAnswer SEPARATOR ',') AS StudentAnswer, ResponseTime, MouseClick, 
    (
    SELECT sum( StudentMark )
    FROM Student_Answer sta
    WHERE sa.StudentId = sta.StudentId
    AND sa.QuestionId = sta.QuestionId
    )StudentMark
    FROM Student st
    INNER JOIN Student_Answer sa ON (st.StudentId = sa.StudentId)
    INNER JOIN Student_Response sr ON (sa.StudentId = sr.StudentId) AND sa.QuestionId = sr.QuestionId
    INNER JOIN Question q ON (sa.QuestionId = q.QuestionId)
    INNER JOIN Answer an ON q.QuestionId = an.QuestionId
    LEFT JOIN Reply r ON q.ReplyId = r.ReplyId
    LEFT JOIN Option_Table o ON q.OptionId = o.OptionId
    LEFT JOIN Session_Taken sta ON (st.StudentId = sta.StudentId)
      WHERE q.SessionId = ?
      GROUP BY sa.StudentId, q.QuestionId
      ORDER BY StudentAlias, q.SessionId, QuestionNo
    ";
    global $mysqli;
$selectedstudentanswerstmt=$mysqli->prepare($selectedstudentanswerqry);
$selectedstudentanswerstmt->bind_param('i',$_POST['session']);
// get result and assign variables (prefix with db)
$selectedstudentanswerstmt->execute(); 
$selectedstudentanswerstmt->bind_result($detailsStudentId,$detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname,$detailsSessionId,
$detailsQuestionId,$detailsQuestionNo,$detailsQuestionContent,$detailsOptionType,$detailsNoofAnswers,$detailsAnswer,$detailsReplyType,$detailsQuestionMarks,
$detailsStudentAnswer,$detailsResponseTime,$detailsMouseClick,$detailsStudentMark); 
4

3 に答える 3

1

empty()は、「0」を空のhttp://php.net/manual/en/function.empty.phpと見なします。したがって、$p_student = empty($_POST["student"])?'':$_POST["student"];$ _POST["student"]が「0」の場合は$p_studentでtrueになります。結果として、以下のケースは常に「デフォルト」であるため、empty()の場合は$p_studentを「0」に設定する必要があります。もちろん$p_question...)。`

    $p_student = empty($_POST["student"])?0:$_POST["student"];  // Now if $_POST['student'] is either 0 or empty $p_student will be 0

    switch($p_student){
    case 0:
        //dont' add where filters
        break;
    default:
        $where[] = 'sa.StudentId = ?';
        $parameters[] .= $_POST["student"];
        $parameterTypes .= 'i';
    }

    // Check whether a specific question was selected
    $p_question = empty($_POST["question"])?0:$_POST["question"]; // Same here, if $_POST['question'] is either 0 or empty $p_question will be 0
    switch($p_question){
    case 0:
        //dont' add where filters
        break;
    default:
        $where[] = 'q.QuestionId = ?';
        $parameters[] .= $_POST["question"];
        $parameterTypes .= 'i';
    }`
于 2013-02-17T17:43:08.260 に答える
1

私はあなたの問題の原因はこれだと信じています:

    // Check whether a specific student was selected
    $p_student = empty($_POST["student"])?'':$_POST["student"];

    switch($p_student){
    case 0:
        //dont' add where filters
        break;
    default:
        $where[] = 'sa.StudentId = ?';
        $parameters[] .= $_POST["student"];
        $parameterTypes .= 'i';
    }

where句に学生を追加するコードは1回だけ実行され、複数の学生が選択されることはサポートされていません。

フォームから学生IDの配列を渡すようにコードを変更すると仮定すると、このようなものが機能するはずです。

if (!empty($_POST['student'])) {

    $students = filter_input_array(INPUT_POST, 'student', FILTER_SANITIZE_NUMBER_INT);

    if ($students !== false) {
        $num_students = count($students);
        $where[]      = 'sa.StudentId IN (' . rtrim(str_repeat('?,', $num_students), ',') . ')';
        $parameters   = array_merge($parameters, $students);
    }
}

いくつかのこと:

  • 消毒されていないデータは絶対に信用せず、使用する前に必ず消毒/フィルタリングしてください。
  • フォームフィールドの名前に追加[]すると(つまり、<select name="student[]">PHPはそれを$_POSTの配列として解釈します。
  • これにより、SQLクエリが複数の結果を返すようになります。つまり$questions、これらの結果がすべて保持されます。
于 2013-02-11T02:01:38.493 に答える
0

私はあなたが後のクロージング}を逃していると思います

// You only need to call bind_param once

今あなたの

if(!empty($where)) {

終わるべき場所で終わらない...

于 2013-02-17T18:43:43.737 に答える