I am developing an online quiz system.
On the administration panel I have a button labeled as "Add question". When I click on the button a modal dialog opens a quiz form containing question sentence (3), question image (4), the examination that will have the question to be added (1), difficulty level (1 to 5) (2), five answer options (5) and two radio buttons (6) which it will be enabled or disabled.
Everything is fine here.
This is Add Question Modal Content
<?php
include_once '../config.php'; //includes class ExamConfig
$cfg = new ExamConfig();
$examsQuery = $cfg->db->query('SELECT id, exam FROM examinations');
$rowExams = $examsQuery->fetchAll(PDO::FETCH_ASSOC);
$diffQuery = $cfg->db->query('SELECT id, difficulty FROM DifficultyLevels');
$rowDiff = $diffQuery->fetchAll(PDO::FETCH_ASSOC);
?>
<form action="" method="post" class="form-signin" enctype="multipart/form-data" id="frm_addQuestion">
<p> This question belongs to:
<select name = "exam" id = "exam" class = "form-control">
<?php
foreach ($rowExams as $re)
{
echo '<option value="' . $re['id'] . '">' . $re['exam'] . '</option>';
}
?>
</select>
</p>
<p> Question Difficulty Level:
<select name = "difficulty" id = "difficulty" class = "form-control">
<?php
foreach ($rowDiff as $rd)
{
echo '<option value="' . $rd['id'] . '">' . $rd['difficulty'] . '</option>';
}
?>
</select>
</p>
<p> Question Text:
<input class = "form-control" type = "text" name = "question" id = "question" /> </p>
<p> Question Picture:
<input type = "file" name = "qPicture" id = "qPicture" /> </p>
<p> <strong> Option 1 (Correct Answer): </strong>
<input class = "form-control success" type = "text" name = "opt1" id = "opt1" /> </p>
<p> Option 2:
<input type = "text" class = "form-control" name = "opt2" id = "opt2" /> </p>
<p> Option 3:
<input type = "text" class = "form-control" name = "opt3" id = "opt3" /> </p>
<p> Option 4:
<input type = "text" class = "form-control" name = "opt4" id = "opt4" /> </p>
<p> Option 5:
<input type = "text" class = "form-control" name = "opt5" id = "opt5" /> </p>
<p> <input type = "radio" name = "enabled" id = "enabled" value = "1" /> Enabled </p>
<p> <input type = "radio" name = "enabled" id = "enabled" value = "0" /> Disabled </p>
<p> <a class = "btn btn-primary btn-block" type = "button" name = "btn_question_save" id = "btn_question_save" onclick="SaveQuestion();"> Save Question</a></p>
</form>
And this is JS file which contains SaveQuestion() function:
function SaveQuestion() {
var request;
// abort any pending request
if (request) {
request.abort();
}
// setup some local variables
var $form = $('#frm_AddQuestion');
// let's select and cache all the fields
var $inputs = $form.find("input, select, button");
// serialize the data in the form
var serializedData = $form.serialize();
// let's disable the inputs for the duration of the ajax request
$inputs.prop("disabled", true);
// fire off the request to /QuestionSave.php
request = $.ajax({
url: "QuestionSave.php",
type: "post",
data: serializedData,
success: function(result)
{
response = result;
}
});
// callback handler that will be called on success
request.done(function(response, textStatus, jqXHR) {
if (response === "0")
{
alert('Hey!'); //record inserted
}
else if( response === "900")
{
alert('Oh noooo!'); //record not inserted
}
});
// callback handler that will be called on failure
request.fail(function(jqXHR, textStatus, errorThrown) {
// log the error to the console
console.error(
"Oops: " +
textStatus, errorThrown
);
});
// callback handler that will be called regardless
// if the request failed or succeeded
request.always(function() {
// reenable the inputs
$inputs.prop("disabled", false);
});
}
And lastly this is the code of QuestionSave.php
<?php
if ( !isset( $_SESSION ) )
{
session_start();
}
include_once '../config.php';
$cfg = new ExamConfig();
if ( isset( $_POST ) )
{
$imgData = fopen( $_FILES[ 'qPicture' ][ 'tmp_name' ], 'rb' );
$questionSaveQuery= $cfg->db->prepare( 'INSERT INTO questions (question, user_id, examid, difficultyid, picture, enabled) VALUES( :question, :user_id, :examid, :difficultyid, :picture, :enabled)' );
$questionSaveQuery->bindValue( ':question', $_POST[ 'question' ], PDO::PARAM_STR );
$questionSaveQuery->bindValue( ':user_id', $_SESSION[ 'user_id' ], PDO::PARAM_INT );
$questionSaveQuery->bindValue( ':examid', $_POST[ 'exam' ], PDO::PARAM_INT );
$questionSaveQuery->bindValue( ':difficultyid', $_POST[ 'difficulty' ], PDO::PARAM_INT );
$questionSaveQuery->bindValue( ':picture', $imgData, PDO::PARAM_LOB );
$questionSaveQuery->bindValue( ':enabled', $_POST[ 'enabled' ], PDO::PARAM_INT );
if ( $questionSaveQuery->execute() )
{
$lid = $cfg->db->lastInsertId();
$optionSaveQuery= $cfg->db->prepare( 'INSERT INTO options
(questionid, answer, correct) VALUES
(:qid1, :opt1, 1),
(:qid2, :opt2, 0),
(:qid3, :opt3, 0),
(:qid4, :opt4, 0),
(:qid5, :opt5, 0)' );
$optionSaveQuery->bindValue( ':qid1', $lid, PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':opt1', $_POST[ 'opt1' ], PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':qid2', $lid, PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':opt2', $_POST[ 'opt2' ], PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':qid3', $lid, PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':opt3', $_POST[ 'opt3' ], PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':qid4', $lid, PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':opt4', $_POST[ 'opt4' ], PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':qid5', $lid, PDO::PARAM_INT );
$optionSaveQuery->bindValue( ':opt5', $_POST[ 'opt5' ], PDO::PARAM_INT );
if ( $optionSaveQuery->execute() )
echo '0';
else
{
echo '901';
$DeleteLastQuestion = $cfg->db->prepare( 'DELETE FROM questions WHERE id = :id' );
$DeleteLastQuestion->bindValue( ':id', $lid, PDO::PARAM_INT );
$DeleteLastQuestion->execute();
}
}
else
echo '900';
}
?>
If I bypass AJAX request and submit form directly to QuestionSave.php
it inserts the question with no problem. But if I use Ajax way, I have got an error as follows:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'picture' cannot be null...
In other words picture is not transferred to QuestionSave.php
and $_FILES[ 'qPicture' ][ 'tmp_name' ]
returns null
. So it breaks the operation. Anyone suggests me a way to get rid of this problem?