【问题标题】:mysql return multi level arraymysql返回多级数组
【发布时间】:2012-08-17 20:37:31
【问题描述】:

我正在处理 PHP 应用程序中相关的三个 MySQL 表。有很多问题的测试,问题有很多答案。我想要做的是循环遍历数据如下:

foreach($tests as $test)
{
    echo $test->testName;

    foreach($test->questions as $question)
    {
        echo $question->questionText;

        foreach($question->answers as $answer)
        {
            echo $answer->answerText;
        }
    }
}

我想知道 MySQL 查询和 PHP 代码以这种方式循环遍历它会是什么?

edit MySQL 不能返回这样的数组,我应该说的是 MySQL + PHP 代码会是什么样子。

为清楚起见,表格是测试、问题和答案。 questions 表包含一个 test_id 列,answers 包含一个 question_id

谢谢!

我希望恢复的结构类似于:

array(
    'testName' = 'Test name string',
    'questions' = array(
        array(
            'questionId' = 1,
            'questionText' = 'Question string',
            'answers' = array(
                array(
                    'answerId' = 1,
                    'answerText' = 'Answer string'
                ),
                array(
                    'answerId' = 2,
                    'answerText' = 'Answer string'
                )
            )
        )
    )
);

编辑

我目前的实现如下,我想做的是预先加载数据而不是执行这么多查询

$tests = getTests();

foreach($tests as $test){

    $questions = getQuestions($test->id);

    foreach($questions as $question){

        $answers = getAnswers($question->id);

        foreach($answers as $answer){

            // do answer things

        }

    }

}

【问题讨论】:

标签: php mysql multidimensional-array


【解决方案1】:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");


$query = "SELECT testname, question, answer
    FROM tests 
    JOIN questions ON (tests.id = question.test_id)
    JOIN answers ON (questions.id = answers.id)
    WHERE 'your condition'
    ORDER BY tests.id, question.id"

$result = $mysqli->query($query);

您可以使用 in_array 函数来获得您想要的结果(您可以制作数组或打印结果)。这是打印值的示例。 (您可以使用 id 代替 name 来改善)

$tests_arr = array();
$questions_arr = array();

while( $row = $result->fetch_array(MYSQLI_ASSOC) )
{
    if(!in_array($row['testname'], $test_arr)
    {
        $test_arr[] = $row['testname'];
        echo $row['testname'];
    }

    if(!in_array($result['question'], $question_arr))
    {
        $questions_arr[] = $row['question'];
        echo $row['question'];
    }

    echo $row['answer'];
}

【讨论】:

  • 由于不再推荐使用 mysql_* 函数,请不要在 OP 未显示它们使用它们的答案中推荐它们的使用。相反,建议使用 Mysqli 或 @ 987654323@ 方法。
  • 哦,谢谢 newfurniturey。不知道那个。将其改为 mysqli
【解决方案2】:

MySQL 不能以您想要的格式返回数组结构 - 它可以做的最好的事情是一个 2D 数组来表示列/行。

两种选择都将在 PHP 中实现。

  1. 为每个测试运行查询;遍历每个测试并运行查询以获取此测试的所有问题;遍历每个问题并运行查询以获取该问题的答案。

例子:

// get each test
$tests = array();
$results = $mysqli->query('SELECT id, name FROM tests;');
while ($test = $results->fetch_object()) $tests[] = $test;
foreach ($tests as $t => $test) {
    // get all questions for this test
    $tests[$t]['questions'] = array();
    $results = $mysqli->query('SELECT id, name FROM questions WHERE test_id = ' . $test['id']);
    while ($question = $results->fetch_object()) $tests[$t]['questions'][] = $question;
    foreach ($tests[$t]['questions'] as $q => $question) {
        // get all answers for this question
        $tests[$t]['questions'][$q]['answers'] = array();
        $results = $mysqli->query('SELECT id, name FROM answers WHERE question_id = ' . $question['id']);
        while ($answer = $results->fetch_object()) $tests[$t]['questions'][$q][] = $answer;
    }
}


2. 使用 MySQL 连接运行单个查询,并预迭代结果列表以构建所需格式的数组。

【讨论】:

    【解决方案3】:

    在纯 SQL 中,您可以进行连接,但这会使您的行变平,行数将是测试 * 问题 * 答案。然后,您必须解析属性并将其映射到适当的对象。像这样的:

    $sql = "SELECT * FROM tests t, questions q, answers a  WHERE q.t_id = t.id AND a.q_id = q.id";
    $rows = // do your fetching, pdo, mysqli, whatever, just get the rows
    
    $tests = array();
    foreach($rows as $row) {
        // map test
        if(!isset($tests[$row['t_id']])) $tests[$row['t_id']] = array(
           // set test attributes here (without the questions)
        );
    
        // map question
        if(!isset($tests[$row['t_id']]['questions'][$row['q_id']])) = array(
           // set question attributes here (without the answers)
        );
    
        // map answer
        if(!isset($tests[$row['t_id']]['questions'][$row['q_id']]['answers'][$row['a_id']])) = array(
           // set answer attributes here 
        );
    }
    

    $tests 数组现在应该具有您需要的层次结构, 但一定要对此进行测试,但即使它不起作用,你也会明白的。

    话虽如此,看看一些ORM-s。 对于最简单的(以一种好的方式)之一,请看一下: http://phpmaster.com/database-interaction-made-easy-with-notorm/

    本教程很容易完成,最后你会得到你所要求的,一组具有属性和基于表关系的良好层次结构的对象。

    【讨论】:

      【解决方案4】:

      你可以LEFT JOIN,这样结果就像:

      test1|question1|answer1
      test1|question1|answer2
      test1|question2|answer1
      test1|question2|answer2
      test2|question1|answer1
      

      然后你以这样一种方式循环遍历它,它们总是按那个顺序出现,所以编写一个循环来获取一行,如果测试自上一个测试以来发生了变化,则移动到数组中的下一个测试。重复问题,最后添加答案。

      一些伪代码

      fetcharray()
      if test > lasttest
        arraytest++
        arrayquestion = 0
      elif question > lastquestion
        arrayquestion++
      
      array[arraytest][arrayquestion][] = fetched array
      

      【讨论】:

        猜你喜欢
        • 2014-08-11
        • 2013-12-04
        • 2014-08-03
        • 1970-01-01
        • 1970-01-01
        • 2012-06-24
        • 2015-02-22
        • 2012-06-06
        • 2015-11-26
        相关资源
        最近更新 更多