My goal is to make a single database hit to generate a JSON array of objects with attributes that could be also be an array of objects, which could also have attributes that array of objects etc of an arbitrary (but known) depth.
I get a 2D array from my database using a PDO object.
$stmt = $this->pdo->prepare($sql);
$stmt->execute($args);
$TwoDimArray = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $TwoDimArray;
So in my example, I have a Quiz, that can have questions, that can have answers. So a depth of 3. So assuming I have a 2D Array such as the table below, how would I make this JSON array using that data. (Note: other data has been removed for clarity sake, but questions and answers could have other attributes.)
Edit: This is my attempt. It is horribly inefficient and not very abstract for the general case but this code will achieve the right answer for small data sets.
$data = ($database -> query($sql,$args)); // the result is $TwoDimArray
$quizes = array();
$quiz_id_list = array();
foreach($data as $quizkey => $quizvalue){
if(!in_array($quizvalue["quiz_id"], $quiz_id_list)) {
array_push($quiz_id_list, $quizvalue["quiz_id"]);
$question_id_list = array();
$questions = array();
foreach ($data as $questionskey => $questionsvalue) {
if ($quizvalue["quiz_id"] == $questionsvalue["quiz_id"] && !in_array($questionsvalue["question_id"], $question_id_list)) {
$answers = array();
array_push($question_id_list, $questionsvalue["question_id"]);
foreach ($data as $answerskey => $answersvalue) {
$myanswer = array();
if ($questionsvalue["question_id"] == $answersvalue["question_id"]) {
$myanswer["answer_id"] = $answersvalue["answer_id"];
array_push($answers, $myanswer);
}
}
$myquestion = array();
$myquestion["question_id"] = $questionsvalue["question_id"];
$myquestion["answers"] = $answers;
array_push($questions, $myquestion);
}
}
$myquiz = array();
$myquiz["quiz_id"] = $quizvalue["quiz_id"];
$myquiz["questions"] = $questions;
array_push($quizes, $myquiz);
}
}
return json_encode($quizes);
The contents of $data looks like this:
array (
0 =>array('quiz_id' => '1', 'question_id' => '1', 'answer_id' => '1',),
1 =>array('quiz_id' => '1', 'question_id' => '1', 'answer_id' => '2',),
...
5 =>array('quiz_id' => '1', 'question_id' => '2', 'answer_id' => '6',),
6 =>array('quiz_id' => '1', 'question_id' => '2', 'answer_id' => '7',),
...
22 =>array('quiz_id' => '2', 'question_id' => '6', 'answer_id' => '23',),
23 =>array('quiz_id' => '2', 'question_id' => '6', 'answer_id' => '24',),
)
The result should return a json object that looks like this:
[
{
"quiz_id": 1,
"questions": [
{"question_id":1, "answers": [{"answer_id":1}, {"answer_id":2}, {"answer_id":3},{"answer_id":4}]},
{"question_id":2, "answers": [{"answer_id":5}, {"answer_id":6}, {"answer_id":7},{"answer_id":8}]},
{"question_id":3, "answers": [{"answer_id":9}, {"answer_id":10}, {"answer_id":11},{"answer_id":12}]}
]
},
{
"quiz_id": 2,
"questions": [
{"question_id":4, "answers": [{"answer_id":13}, {"answer_id":14}, {"answer_id":15},{"answer_id":16}]},
{"question_id":5, "answers": [{"answer_id":17}, {"answer_id":18}, {"answer_id":19},{"answer_id":20}]},
{"question_id":6, "answers": [{"answer_id":21}, {"answer_id":22}, {"answer_id":23},{"answer_id":24}]}
]
}
]