I'm working on a quiz application for training purposes and I think I'm done with most of it. However, I'm not comfortable with what I've done: it seems to be complicated and unprofessional and I would like to make it more organized and simple to understand.
first the database contains a three simple table:
quiz table:
id | name
questions table:
id | question | quiz_id(fk from quiz table) |
answers table:
id | name | questions_id(fk from questions table) | state(right or wrong)
1. the first task is a page to show all available quizes:
the data part
public function getQuizes() {
$stmt = $this->dbconn->prepare("SELECT id, name FROM {$this->table}");
$stmt->execute();
return $stmt->fetchAll();
}
the controller part
// get all quizes
$quizes = $this->quizModel->getQuizes();
// pass the data to the view
$this->callView('quiz/index',$quizes);
the view part to display data
<?php include VIEWS . 'templates/header.php'; ?>
<h3>Available Quizes:</h3>
<ul class="links-list">
<?php foreach ($records as $record): ?>
<li>
<a href=" <?= BASEPATH . 'quiz/getquiz/' . $record['id']?>">
<?= $record['name']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php include VIEWS . 'templates/footer.php'; ?>
2. the second task is a page to show quiz and it's questions and possible answers
the data part
public function getQuizById($id) {
$results = [];
$stmt = $this->dbconn->prepare(
"SELECT DISTINCT quiz.name quizName, questions.question question, answers.name answer, answers.id answerId
FROM quiz
inner Join questions
ON quiz.id = questions.quiz_id
inner join answers
on questions.id = answers.question_id
where quiz.id = :id"
);
$stmt->bindParam(':id', $id);
$stmt->execute();
// group the information
while( $row = $stmt->fetch(PDO::FETCH_ASSOC) ){
$results[$row['quizName']][$row['question']][] = [$row['answerId'], $row['answer']];
}
return $results;
}
controller part
// get single quiz
public function getquiz($id) {
// get the quiz
$quizes = $this->quizModel->getQuizById($id);
// pass the data to the view
$this->callView('quiz/single',$quizes);
}
single.php view to display the data
<?php include VIEWS . 'templates/header.php'; ?>
<?php
foreach ($records as $quiz => $questions):
?>
<h3> <?= $quiz ?> quiz:</h3>
<form action="<?= BASEPATH . 'quiz/postanswers' ?>" method="post">
<ul class="links-list">
<?php
foreach ($questions as $question => $answers):
?>
<li class="highlight-panel">
<?= $question ?>
</li>
<?php
foreach ($answers as $answer):
?>
<li>
<input type="radio" name="<?= $question ?>" value="<?= $answer[0] ?>"/>
<?= $answer[1] ?>
</li>
<?php
endforeach;
?>
<?php
endforeach;
?>
</ul>
<br>
<input type="submit" value="submit answers" />
</form>
<?php
endforeach;
?>
<?php include VIEWS . 'templates/footer.php'; ?>
3. the third task is a report page to show the final results to the user after posting the answers
the model part
public function getAnswerInfo($id) {
$stmt = $this->dbconn->prepare(
"SELECT DISTINCT quiz.name quizname, questions.id question_id, questions.question question, answers.name answer, answers.state
FROM quiz
inner Join questions
ON quiz.id = questions.quiz_id
inner join answers
on questions.id = answers.question_id
where answers.id = :id"
);
$stmt->bindParam(':id', $id);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC) ;
}
public function getrightanswer($qid) {
$stmt = $this->dbconn->prepare(
"SELECT name from answers where state = 1 and question_id = :qid"
);
$stmt->bindParam(':qid', $qid);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
the controller part
public function postanswers() {
$results = [];
$groupedResults = [];
$counter = 0;
if( isset($_POST) ){
foreach ($_POST as $answerid) {
$results[] = $this->quizModel->getAnswerInfo($answerid);
}
foreach ($results as $key => $value){
if($value['state'] == 1){
$counter++;
$useranswer = 1;
} else {
$useranswer = 0;
}
$groupedResults[$value['question']][$value['answer']][] = ['rightanswer' => $this->quizModel->getrightanswer($value['question_id']), 'useranswerscore' => $useranswer];
}
$quizname = $results[0]['quizname'];
$data = [$groupedResults, $quizname, $counter, count($results)];
$this->callView('quiz/report', $data);
}
}
the view part to display the final report
<?php include VIEWS . 'templates/header.php'; ?>
<h3> Your answers for <?= $records[1] ?> quiz: </h3>
<table>
<thead>
<tr>
<td>Question</td>
<td>Your answer</td>
<td>Right answer</td>
<td>Points</td>
</tr>
</thead>
<tbody>
<?php
// loop through the questions
foreach ($records[0] as $question => $answer):
?>
<tr>
<td><?= $question ?></td>
<?php
// loop through the answers
foreach ($answer as $useranswer => $answersinfo):
?>
<td><?= $useranswer ?></td>
<?php
// the answers info
foreach ($answersinfo as $value):
?>
<td><?= $value['rightanswer']['name'] ?></td>
<td><?= $value['useranswerscore'] ?></td>
<?php endforeach; ?>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
<tr>
<td>
Final results : <?= $records[2] . '/' . $records[3]; ?>
</td>
</tr>
</tbody>
</table>
<?php include VIEWS . 'templates/footer.php'; ?>
That's what I've done with the app so far and as i said i would like to find a better way to organize every thing. I would like to hear your suggestions on how to improve it.