I have 2 drop down menus where the user can use the drop down menus to filter whih students and questions they wish to see. The possible types of filters are:
- Select All Students and All Questions
- Select All Students and One question
- Select All Questions and one Student
- Select One Student and One Question
Below is drop down menus:
<p>
<strong>Student:</strong>
<select name="student" id="studentsDrop">
<option value="All">All</option>
<?php
while ( $currentstudentstmt->fetch() ) {
$stu = $dbStudentId;
if(isset($_POST["student"]) && $stu == $_POST["student"])
echo "<option selected='selected' value='$stu'>" . $dbStudentAlias . " - " . $dbStudentForename . " " . $dbStudentSurname . "</option>" . PHP_EOL;
else
echo "<option value='$stu'>" . $dbStudentAlias . " - " . $dbStudentForename . " " . $dbStudentSurname . "</option>" . PHP_EOL;
}
?>
</select>
</p>
<p>
<strong>Question:</strong>
<select name="question" id="questionsDrop">
<option value="All">All</option>
<?php
while ( $questionsstmt->fetch() ) {
$ques = $dbQuestionId;
if(isset($_POST["question"]) && $ques == $_POST["question"])
echo "<option selected='selected' value='$ques'>" . $dbQuestionNo . "</option>" . PHP_EOL;
else
echo "<option value='$ques'>" . $dbQuestionNo . "</option>" . PHP_EOL;
}
?>
</select>
</p>
Now I want to set up a mysqli query which determines on the students and questions selected from the drop down menu.
My question is simply do I need to set up 4 queries checking for the 4 possibilities I mentioned from the drop down menus or is there are a shorter way?
Do I have to use:
if ($_POST['question'] == 'All' && if ($_POST['student'] == 'All'){){
//NO WHERE CLAUSE
if ($_POST['question'] == 'All' && if ($_POST['student'] != 'All'){){
//WHERE CLAUSE FOR FINDING SELECTED STUDENT
if ($_POST['question'] != 'All' && if ($_POST['student'] == 'All'){){
//WHERE CLAUSE FOR FINDING SELECTED QUESTION
if ($_POST['question'] != 'All' && if ($_POST['student'] != 'All'){){
//WHERE CLAUSE FOR FINDING SELECTED QUESTION AND SELECTED STUDENT
UPDATE:
What I have at moment:
function AssessmentIsSubbmitted()
{
if(isset($_POST['answerSubmit'])) // we have subbmited the first form
{
//QUERY 1: Student details depending on selected student(s)
if ($_POST['student'] == 'All'){
$selectedstudentqry = "
SELECT
StudentAlias, StudentForename, StudentSurname
FROM Student s
INNER JOIN Student_Session ss ON s.StudentId = ss.StudentId
WHERE SessionId = ?
ORDER BY StudentAlias
";
global $mysqli;
$selectedstudentstmt=$mysqli->prepare($selectedstudentqry);
// You only need to call bind_param once
$selectedstudentstmt->bind_param("i",$_POST["session"]);
// get result and assign variables (prefix with db)
$selectedstudentstmt->execute();
$selectedstudentstmt->bind_result($detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname);
$selectedstudentstmt->store_result();
$selectedstudentnum = $selectedstudentstmt->num_rows();
}else{
$selectedstudentqry = "
SELECT
StudentAlias, StudentForename, StudentSurname
FROM
Student
WHERE
(StudentId = ?)
ORDER BY StudentAlias
";
global $mysqli;
$selectedstudentstmt=$mysqli->prepare($selectedstudentqry);
// You only need to call bind_param once
$selectedstudentstmt->bind_param("i",$_POST["student"]);
// get result and assign variables (prefix with db)
$selectedstudentstmt->execute();
$selectedstudentstmt->bind_result($detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname);
$selectedstudentstmt->store_result();
$selectedstudentnum = $selectedstudentstmt->num_rows();
}
//QUERY 2: Question details depending on selected question(s)
if ($_POST['question'] == 'All'){
$selectedquestionqry = " SELECT q.QuestionNo, q.QuestionContent, o.OptionType, q.NoofAnswers, GROUP_CONCAT( DISTINCT Answer
ORDER BY Answer
SEPARATOR ',' ) AS Answer, r.ReplyType, q.QuestionMarks
FROM Question q
LEFT 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
WHERE SessionId = ?
GROUP BY q.QuestionId
ORDER BY q.QuestionId";
";
global $mysqli;
$selectedquestionstmt=$mysqli->prepare($selectedquestionqry);
// You only need to call bind_param once
$selectedstudentstmt->bind_param("i",$_POST["session"]);
// get result and assign variables (prefix with db)
$selectedquestionstmt->execute();
$selectedquestionstmt->bind_result($detailsQuestionNo,$detailsQuestionContent,$detailsOptionType,$detailsNoofAnswers,
$detailsAnswer,$detailsReplyType,$detailsQuestionMarks);
$selectedquestionstmt->store_result();
$selectedquestionnum = $selectedquestionstmt->num_rows();
}else{
$selectedquestionqry = "
SELECT q.QuestionNo, q.QuestionContent, o.OptionType, q.NoofAnswers, GROUP_CONCAT( DISTINCT Answer
ORDER BY Answer
SEPARATOR ',' ) AS Answer, r.ReplyType, q.QuestionMarks
FROM Question q
LEFT 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
WHERE QuestionId = ?
GROUP BY q.QuestionId
ORDER BY q.QuestionId
";
global $mysqli;
$selectedquestionstmt=$mysqli->prepare($selectedquestionqry);
// You only need to call bind_param once
$selectedquestionstmt->bind_param("i",$_POST["question"]);
// get result and assign variables (prefix with db)
$selectedquestionstmt->execute();
$selectedquestionstmt->bind_result($detailsQuestionNo,$detailsQuestionContent,$detailsOptionType,$detailsNoofAnswers,
$detailsAnswer,$detailsReplyType,$detailsQuestionMarks);
$selectedquestionstmt->store_result();
$selectedquestionnum = $selectedquestionstmt->num_rows();
}
//QUERY 3: Student Answers depending on selected student(s) and selected question(s)
$studentanswerqry = "
SELECT
sa.StudentId, sa.QuestionId, GROUP_CONCAT(DISTINCT StudentAnswer ORDER BY StudentAnswer SEPARATOR ',') AS StudentAnswer, ResponseTime, MouseClick, StudentMark
FROM Student_Answer sa
INNER JOIN Student_Response sr ON sa.StudentId = sr.StudentId
WHERE
(sa.StudentId = ? AND sa.QuestionId = ?)
GROUP BY sa.StudentId, sa.QuestionId
";
global $mysqli;
$studentanswerstmt=$mysqli->prepare($studentanswerqry);
// You only need to call bind_param once
$studentanswerstmt->bind_param("ii",$_POST["student"], $_POST["question"]);
// get result and assign variables (prefix with db)
$studentanswerstmt->execute();
$studentanswerstmt->bind_result($detailsStudentAnswer,$detailsResponseTime,$detailsMouseClick,$detailsStudentMark);
$studentanswerstmt->store_result();
$studentanswernum = $studentanswerstmt->num_rows();
}
?>
This is code I used where there are 64 permutations of user input. There can be a rider ID from another page, partial first and/or last name, a year, a month or a course ID.
Construct part of the where clause with a variety of ANDs, IS LIKE, etc.
Here is the query.
Prepare and bind the parameters.
I solved a similar problem this way. Where $parmMap is constructed with powers of 2 (1,2) as I detect each optional WHERE clause item and append the appropriate AND fieldName = ?.
I won't be using this though for another query that has six optional where clause conditions! I've discovered
call_user_func_array
.You can iteratively build a
WHERE
clause. Consider that aWHERE
clause does explicit filtering, so for cases where you're selecting "all" of something, you don't need to add any filters. The other filters build upon each other, so we can simply join them withAND
s in theWHERE
:Okay, so looking at your update, you have a fairly complex set of queries, but it's possible to combine it into one statement. Give this a try:
I think this will do what you want. I wasn't quite sure about which fields are part of
Student_Response
and which are part ofStudent_Answer
so you might have to fiddle with the columns in theSELECT
.Unfortunately that approach doesn't work for your use case. But we can still consider how the original logic I proposed would work with one of your queries given:
Notice how we've simply moved the outer
if
s to more specific places within the code to decrease code duplication. If you see duplication like you have, there's a very good chance that you're doing something like making your conditionals too broad. You're definitely on the right track with trying to simplify this and reduce redundancy, though.