<p>Have you considered doing this in Twig instead? If your needs are complex, then a custom module in PHP might be best, but since you described it as a &quot;simple&quot; quiz, I'd probably go with Twig. Here's a fully functional example:</p>
<pre class="lang-twig prettyprint-override"><code>{% set allQuestions = entry.quiz.all() %}
&lt;form method=&quot;post&quot;&gt;
    {% for question in allQuestions %}
        &lt;h3&gt;{{ question.question }}&lt;/h3&gt;
        {% for answer in question.answers %}
            &lt;label for=&quot;answer-{{ question.id }}-{{ loop.index0 }}&quot;&gt;
                &lt;input type=&quot;radio&quot; name=&quot;answers[{{ loop.parent.loop.index0 }}]&quot; value=&quot;{{ loop.index0 }}&quot; id=&quot;answer-{{ question.id }}-{{ loop.index0 }}&quot;&gt;
                {{ answer.answer }}
            &lt;/label&gt;
        {% endfor %}
    {% endfor %}
    &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;

{% if craft.app.request.param('answers') %}
    {% set correctAnswersByQuestion = [] %}
    {% for question in allQuestions %}
        {% set correctAnswer = question.answers|map(answer =&gt; answer.correct ? true : false) %}
        {% set correctAnswersByQuestion = correctAnswersByQuestion|push(correctAnswer) %}
    {% endfor %}

    &lt;h2&gt;Results:&lt;/h2&gt;
    {% set totalCorrect = 0 %}
    {% for questionIndex, answerIndex in craft.app.request.param('answers') %}
        &lt;p&gt;Question {{ questionIndex+1 }} was {{ correctAnswersByQuestion[questionIndex][answerIndex] ? 'correct' : 'incorrect' }}&lt;/p&gt;
        {% set totalCorrect = correctAnswersByQuestion[questionIndex][answerIndex] ? totalCorrect+1 : totalCorrect %}
    {% endfor %}

    &lt;h2&gt;Score:&lt;/h2&gt;
    {{ totalCorrect/allQuestions|length * 100 }}%
{% endif %}
</code></pre>

CC BY-SA 4.0
2023-02-23T00:15:23.100Z
Thanks! I hadn't really considered it, but that's an amazing start. I did say simple, but I would like the quiz to evolve in the future; for example, saving results to a User's profile, and possibly text input fields rather than just radio inputs.
supazu
CC BY-SA 4.0
2023-02-22T23:38:46.250Z
2023-02-23T10:54:49.213Z
2023-02-23T10:54:49.213Z
James Smith
<p>I'm trying to set up a simple quiz module. I'm using a Matrix field called <code>quiz</code>, with a plain text <code>question</code> field and an <code>answers</code> table field. In the table field, there's two columns, plain text <code>answer</code> and checkbox <code>correct</code>. See image:</p>
<p><a href="https://i.sstatic.net/8DT4z.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/8DT4z.jpg" alt="enter image description here" /></a></p>
<p>The idea being that there's only one correct answer.</p>
<p><strong>EDIT:</strong>
Using James' amazing code as a base, I've tried to get that into PHP and it's coming along ok. Still working on it...</p>
<pre><code>$userAnswers = Craft::$app-&gt;getRequest()-&gt;getBodyParam('answers');
$user = Craft::$app-&gt;getUser()-&gt;getIdentity();

$allQuestions = $quiz-&gt;quizMatrix-&gt;all();
$numberOfQuestions = count($allQuestions);

$correctAnswersByQuestion = [];

foreach ($allQuestions as $question) {
    $correctAnswer = array_map(function($answer) {
        return (bool)$answer['correct'];
    }, $question['answers']);
    $correctAnswersByQuestion[] = $correctAnswer;
}

$totalCorrect = 0;

foreach ($userAnswers as $key =&gt; $value) {
    $questionIndex = $key;
    $answerIndex = $value;
    $isCorrect = $correctAnswersByQuestion[$questionIndex][$answerIndex];
    echo &quot;&lt;p&gt;Question &quot; . ($questionIndex+1) . &quot; was &quot; . ($isCorrect ? 'correct' : 'incorrect') . &quot;&lt;/p&gt;&quot;;
    $totalCorrect += $isCorrect ? 1 : 0;
}

$score = ($totalCorrect / $numberOfQuestions) * 100;
$data = 'Your score is '.$score.'%';
$response = Craft::$app-&gt;getResponse();
$response-&gt;data = $data;
return $response;

</code></pre>

<modules>
Creating a multiple choice quiz module
# Creating a multiple choice quiz module

(Asked by: username_0 on 2023-02-22)

I'm trying to set up a simple quiz module. I'm using a Matrix field called quiz, with a plain text question field and an answers table field. In the table field, there's two columns, plain text answer and checkbox correct. See image:

The idea being that there's only one correct answer.
EDIT:
Using James' amazing code as a base, I've tried to get that into PHP and it's coming along ok. Still working on it...
$userAnswers = Craft::$app->getRequest()->getBodyParam('answers');
$user = Craft::$app->getUser()->getIdentity();

$allQuestions = $quiz->quizMatrix->all();
$numberOfQuestions = count($allQuestions);

$correctAnswersByQuestion = [];

foreach ($allQuestions as $question) {
    $correctAnswer = array_map(function($answer) {
        return (bool)$answer['correct'];
    }, $question['answers']);
    $correctAnswersByQuestion[] = $correctAnswer;
}

$totalCorrect = 0;

foreach ($userAnswers as $key => $value) {
    $questionIndex = $key;
    $answerIndex = $value;
    $isCorrect = $correctAnswersByQuestion[$questionIndex][$answerIndex];
    echo "Question " . ($questionIndex+1) . " was " . ($isCorrect ? 'correct' : 'incorrect') . "";
    $totalCorrect += $isCorrect ? 1 : 0;
}

$score = ($totalCorrect / $numberOfQuestions) * 100;
$data = 'Your score is '.$score.'%';
$response = Craft::$app->getResponse();
$response->data = $data;
return $response;

**Tags:** modules


---

## 1 answers

### Answer by username_1 on 2023-02-22. Score: 3 | Accepted answer

Have you considered doing this in Twig instead? If your needs are complex, then a custom module in PHP might be best, but since you described it as a "simple" quiz, I'd probably go with Twig. Here's a fully functional example:
{% set allQuestions = entry.quiz.all() %}

    {% for question in allQuestions %}
        {{ question.question }}
        {% for answer in question.answers %}
            
                
                {{ answer.answer }}
            
        {% endfor %}
    {% endfor %}
    Submit


{% if craft.app.request.param('answers') %}
    {% set correctAnswersByQuestion = [] %}
    {% for question in allQuestions %}
        {% set correctAnswer = question.answers|map(answer => answer.correct ? true : false) %}
        {% set correctAnswersByQuestion = correctAnswersByQuestion|push(correctAnswer) %}
    {% endfor %}

    Results:
    {% set totalCorrect = 0 %}
    {% for questionIndex, answerIndex in craft.app.request.param('answers') %}
        Question {{ questionIndex+1 }} was {{ correctAnswersByQuestion[questionIndex][answerIndex] ? 'correct' : 'incorrect' }}
        {% set totalCorrect = correctAnswersByQuestion[questionIndex][answerIndex] ? totalCorrect+1 : totalCorrect %}
    {% endfor %}

    Score:
    {{ totalCorrect/allQuestions|length * 100 }}%
{% endif %}

> **Comments:**
> **username_0**: Thanks! I hadn't really considered it, but that's an amazing start. I did say simple, but I would like the quiz to evolve in the future; for example, saving results to a User's profile, and possibly text input fields rather than just radio inputs.  

---

