PHP - loop & lastInsertId()


PHP - loop & lastInsertId()

我有这样的代码,它将执行对问题、选择和多选项表的插入。我成功地插入了问题和选择表,但我没能做到的是多选项表。

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());
    }
}

这是数据库中的示例输出。

问题表

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

选择表

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

选择表中的问题问题表中的id

我想在多选项表中实现的目标。

多选项表

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

多选表中的问题问题表中的id

我对如何做到这一点感到困惑,我想向你们咨询一下。我该怎么做才能做到这一点?

正如我所说,我认为您根本不应该存储这些列表。存储逗号分隔的值通常被认为是糟糕的设计,此外,数据库中已经有了所需的所有信息,因此这些信息也是多余的。

如果你无论如何都想这样做,我认为有四种解决方案。

1)在开始新问题时插入答案缺点是你必须在循环后再次做同样的事情来保存最后一个问题的选择。代码的结构看起来是这样的(为了简洁起见,将其精简)。

$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)将ID保存在一个大数组中,然后存储这些ID您可以将答案保存在嵌套数组中。主级别的关键是问题ID。每个问题都存储一个答案数组(或字符串,但我认为数组更容易)。插入问题和答案后,您可以在数组中循环并插入所有多选项。

这应该很好用,除非你有数百万个问题。最终$allAnswerIDs可能会变得太大,无法容纳内存,但我认为在这种情况下,它不会很快成为问题。

$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)在循环之后使用大容量插入您可以编写一个稍微复杂一点的SQL语句,同时插入所有这些语句,如:

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

您可以在脚本结束时执行一次该语句,它将使数据库一次生成多选项表的全部内容。

4)查看正如您所看到的,方法3中的(相对简单的)select显示了您希望在多选项表中拥有的所有信息,因此您可以考虑将其作为数据库中的视图,而不是将其插入表中。这样,您根本不必存储信息。您的PHP代码将更容易,数据库将更干净,并且您可以像从表中查询一样从视图中进行查询。