0

I have this code that will perform an insert to the question, choice and multichoice table. I managed to accomplish in inserting question and choice table, what I failed to do is the multichoice table.

require("dbOption/Db.class.php");
$question       =   new Db();
$choice         =   new Db();
$multichoice    =   new Db();
$entries = array(
    0 => '1. What foo?',
    1 => 'a. foo1',
    2 => 'b. foo2',
    3 => 'c. foo3',
    4 => 'd. foo4',
    5 => '2. 2 + 2 is?',
    6 => 'a. test1',
    7 => 'b. test2',
    8 => 'c. test3',
    9 => 'd. test4',
);

$answerIDs    = "";
$questionID   = "";

$multipleChoice = array();

foreach ($entries as $entry) {
    if(is_numeric(substr($entry, 0, 1)) === true) {
        echo "<pre>";
            var_dump($entry);
        echo "<pre>";
        $question->query("INSERT INTO question(q_name) VALUES(:question)",array("question"=>$entry));
        $questionID = $question->lastInsertId();
    } else {
        echo "<pre>";
            var_dump($entry);
        echo "<pre>";
        $answer->query("INSERT INTO choice(choices,question) VALUES(:choices, :question)",array("choices"=>$entry, "question"=>$questionID));
        if ($answerIDs === "")
            $answerIDs = $choice->lastInsertId();
        else
            // store last inserted ids in choice table and separate it with ","
            $answerIDs .= ("," . $choice->lastInsertId());
    }
}

This is the sample output in the db.

question table

id     q_name
1   1. What foo?
2   2. 2 + 2 is?

choice table

id   choices    question  correct
1   a. foo1        1       0
2   b. foo2        1       0
3   c. foo3        1       0
4   d. foo4        1       0
5   a. test1       2       0
6   b. test2       2       0
7   c. test3       2       0
8   d. test4       2       0

question in choice table is the id from question table

What I want to achieve in multichoice table.

multichoice table

 id  question  mc_answers
  1    1        1,2,3,4
  2    2        5,6,7,8

question in multichoice table is the id from question table

I’m confused on how to do this, I would like to consult it to you guys. What should I do to achieve this?

3
  • Sounds like bad design. You already can find all answers of a question by looking for the question id, so now you want to store redundant information in a bad (comma separated) way. Commented Apr 6, 2015 at 8:05
  • There is no difference, I just edited my question and added some details... Commented Apr 6, 2015 at 8:08
  • Actually, I am trying to imitate a certain design from Moodle db, the multiple choice type question. I apologize for having a bad design... Commented Apr 6, 2015 at 8:11

1 Answer 1

1

Like I said, I don't think you should store those lists at all. Storing comma separated values is considered bad design in general, and besides you already have all the information you need in the database, so that information would be redundant too.

If you want to do this anyway, I think there are four solutions.

1) Insert the answers when you start a new question. Disadvantage is that you have to do the same thing again after the loop to save the choices of the last question. Structure of the code would look like this (stripped down for brevity).

$answerIDs = "";

foreach ($entries as $entry) {
    if(is_numeric(substr($entry, 0, 1)) === true) {
        if ($answerIDs !== "") {
            // First insert multi select answers

            // Reset the answers for the new question.
            $answerIDs = "";
        }

        // Then insert question as you do now.
    } else {
        // Insert answers and store ID in $answerIDs as you do now.
    }
}

if ($answerIDs !== "") {
    // Store answers (again).
}

2) Keep IDs in a big array, and store those afterwards. You can save the answers in a nested array. The key of the main level is the question ID. Per question you store an array (or a string, but I think array is easier) of answers. After inserting the questions and answers, you can loop through the array and insert all the multiple choices.

This should work fine, unless you've got millions of questions. Eventually $allAnswerIDs might become too big for memory, but I don't think it will be a problem soon in this scenario.

$allAnswerIDs = array();

foreach ($entries as $entry) {
    if(is_numeric(substr($entry, 0, 1)) === true) {
        // Insert question as you do now.

        // Store the question ID in the array.
        $allAnswerIDs[$questionId] = array();
    } else {
        // Insert answer.

        // Store ID in $answerIDs as an array (or as a string, if you like).
        $allAnswerIDs[$questionID][] = $answerID;
    }
}

foreach ($allAnswerIDs as $questionID => $questionAnswerIDs) {
    // Build a string of the answers per question.
    $answerIDs = implode(',', $questionAnswerIDs);

    // Insert the multiple choice row using $questionID and $answerIDs.
}

3) Use a bulk insert after the loop. You can write a single, slightly more complex SQL statement that inserts all of them at once, like:

INSERT INTO multichoice(question, mc_answers)
SELECT
  question,
  GROUP_CONCAT(choices) as AnswerIDs
FROM
  Choice

You can execute this statement once at the end of your script, and it will make the database generate the entire content for the multichoice table at once.

4) Make a view. As you can see, the (relatively simple) select in method 3 shows all the information you want to have in the multichoice table, so instead of inserting it in the table, you may consider to make it a view instead in the database. That way, you don't have to store the information at all. Your PHP code will be easier, your database cleaner, and you can query from the view as you would from the table.

Sign up to request clarification or add additional context in comments.

1 Comment

This really helped a lot! Thanks a lot for the informative details!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.