4

PHPアプリケーションに関連する3つの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コードがこの方法でループすることです。

編集MySQLはこのような配列を返すことはできません。私が言わなければならないのは、MySQL+PHPコードがどのようになるかということです。

わかりやすくするために、表はテスト、質問、および回答です。質問テーブルにはtest_id列が含まれ、回答には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

        }

    }

}
4

4 に答える 4

3
$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を使用できます)

$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'];
}
于 2012-08-22T12:28:54.603 に答える
1

MySQL は、希望する形式で配列構造を返すことはできません。できる最善の方法は、列/行を表す 2D 配列です。

2 つの代替案は、どちらも 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 結合を使用して単一のクエリを実行し、結果のリストを事前に反復処理して、必要な形式の配列を構築します。

于 2012-08-22T12:16:35.277 に答える
1

プレーンな 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を見てください。(良い意味で) 最も単純なものの 1 つについては、これをご覧ください: http://phpmaster.com/database-interaction-made-easy-with-notorm/

チュートリアルは非常に簡単で、最終的には、プロパティを持つ一連のオブジェクトと、テーブルのリレーションに基づいた適切な階層を備えた、まさに求めていたものを手に入れることができます。

于 2012-08-22T12:25:49.847 に答える
0

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
于 2012-08-22T12:20:49.080 に答える