MySQL to nested JSON - php

This is almost exactly what I want, but that question hasn't been answered and it's been a year. I've managed to get close, I think, but numbers are being printed as keys. In my example it shows up on line 47, but it is repeated for every "course_name" in the actual file.
[
{
"school_name": "Projects",
"terms": [
{
"term_name":"category_name#1",
"departments": [
{
"department_name":"sub_category_name1",
"department_code":"category code text here",
"courses":[
{
"course_name": "project1",
"course_code":"project 1 code text goes here",
"sections":[
{
"section_code":"mike",
"unique_id":"xxx#mail.com"
},
{
"section_code":"dan",
"unique_id":"xxx#gmail.com"
}
]
},
{
"course_name": "project2",
"course_code":"project 2 code text goes here",
"sections":[
{
"section_code":"steve",
"unique_id":"xxx#mail.com"
},
{
"section_code":"chris",
"unique_id":"xxx#gmail.com"
}
]
}
]
},
{
"department_name": "sub_category_name2",
"department_code":"sub category description text goes here..",
"courses": {
-->>> "69": {
"course_name": "project3",
"course_code":"project3 code text goes here ",
"sections":[
{
"section_code":"Alex",
"unique_id":"xxx#gmail.com"
}
]
}
}
}
]
}
]
}
]
Here is the query I am using and an example of data being returned.
SELECT school_name, term_name, department_name, department_code, course_code, course_name, section_code, magento_course_id
FROM schools INNER JOIN term_names ON schools.id=term_names.school_id INNER JOIN departments ON schools.id=departments.school_id INNER JOIN
adoptions ON departments.id=adoptions.department_id
"UCA-2" "SPRING 2013" "ACCOUNTING" "ACCT" "3315" "COST ACCOUNTING" "10258" 10311
What I have is being generated with this code.
$row_array = array();
$terms = array();
$departments = array();
$courses = array();
$h = 0;
$i = 0;
$j = 0;
while ($row = mysqli_fetch_assoc($fetch)) {
$row_array[$row['school_name']]['school_name'] = $row['school_name'];
$akey = array_search($row['term_name'], $terms);
if ($akey === FALSE) {
$m = $h++;
$terms[] = $row['term_name'];
$row_array[$row['school_name']]['terms'][$m]['term_name'] = $row['term_name'];
} else {
$m = $akey;
}
$key = array_search($row['department_code'], $departments);
if ($key === FALSE) {
$k = $i++;
$departments[] = $row['department_code'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['department_name'] = $row['department_name'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['department_code'] = $row['department_code'];
} else {
$k = $key;
}
$skey = array_search($row['course_code'], $courses);
if ($skey === FALSE) {
$l = $j++;
$courses[] = $row['course_code'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['course_name'] = $row['course_name'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['course_code'] = $row['course_code'];
} else {
$l = $skey;
}
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['sections'][] = array('section_code' => $row['section_code'], 'unique_id' => $row['magento_course_id']);
}
How do I generate this JSON without those numbers showing up?

I think you have some key & encoding problems. Too much key usage, excessive loops in your code. Maybe you should tidy your sql query.
Since you are setting keys for courses, JSON shows it.
Try removing the key after "['courses']" in your last line such as;
Change ['courses'][$l] to ['courses'][]
At the end, encode the array for JSON.
$result = json_encode($result);

Related

PHP: How to Group and Sum Up in Array

This is my array
array(
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"15.00"],
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"13.50"],
['studentId'=>"M100030","isbn"=>"0143105426",'price'=>"20.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"21.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"23.00"],
['studentId'=>"M100035","isbn"=>"0199535566",'price'=>"14.00"],
['studentId'=>"M103233","isbn"=>"0061964360",'price'=>"18.50"],
);
I want to group the studentId and isbn then sum up the price to JSON
{
"M100030":{
"0199535566":{
"amount":"28.50"
},
"0143105426":{
"amount":"20.00"
}
},
"M100035":{
"1604501480":{
"amount":"44.00"
},
"0199535566":{
"amount":"14.00"
}
},
"M103233":{
"0061964360":{
"amount":"18.50"
}
}
}
The method I tried so far to group the studentId and isbn, but not able to get the expected result. Anyone can correct my code?
foreach ($check['rentout'] as $key=> $values)
{
$keys = $values['studentId'];
if (!array_key_exists($keys,$trx)){
$trx[$keys] = array('isbn'=>$values['isbn'],'amount'=>$values['price']);
}else{
$trx[$keys]['amount'] = $trx[$keys]['amount']+$values['price'];
}
}
$students = array(
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"15.00"],
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"13.50"],
['studentId'=>"M100030","isbn"=>"0143105426",'price'=>"20.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"21.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"23.00"],
['studentId'=>"M100035","isbn"=>"0199535566",'price'=>"14.00"],
['studentId'=>"M103233","isbn"=>"0061964360",'price'=>"18.50"],
);
I Created variable $res and I looped over $students and get the $student_id and do a test if there is no isbn for this student, If So set their amount to the initial value, and loop again if we find it again accumulate its prices to amount, and do this again and again to all students in the array.
$res = [];
foreach ($students as $key => $student) {
$student_id = $student['studentId'];
if (!isset($res[$student_id][$student["isbn"]])){
$res[$student_id][$student["isbn"]]["amount"] = $student['price'];
}else{
$res[$student_id][$student["isbn"]]["amount"] += $student['price'];
}
}
echo "<pre>";
echo json_encode($res, JSON_PRETTY_PRINT);
Print(as excpected)
{
"M100030": {
"0199535566": {
"amount": 28.5
},
"0143105426": {
"amount": "20.00"
}
},
"M100035": {
"1604501480": {
"amount": 44
},
"0199535566": {
"amount": "14.00"
}
},
"M103233": {
"0061964360": {
"amount": "18.50"
}
}
}

Generating desirable JSON format in PHP

I amnot familiar php arrays. Therefore I couldn't solve that problem :
My data comes from database. I didn't post database connection parts, they work perfectly. As I understand I need to use multidimensional array. My Json format should be like this
{
"monthly":[
{
"id":1,
"name":"This is a JSON event",
"startdate":"2016-9-15",
"enddate":"2016-9-15",
"starttime":"12:00",
"endtime":"2:00",
"color":"#FFB128",
"url":""
},
{
"id":2,
"name":"This is a JSON event",
"startdate":"2019-3-25",
"enddate":"2019-3-25",
"starttime":"12:00",
"endtime":"23:00",
"color":"#EF44EF",
"url":""
}
]
}
My PHP script (relevant part) :
try {
$q = "SELECT * FROM eventcalendar";
$res = $db->prepare($q);
$res->execute();
if ($res->rowCount() != 0) {
$data = array('monthly' => array());
$push_array = array();
foreach ($res as $key) {
$data['monthly']['id'] = $key['id'];
$data['monthly']['name'] = $key['name'];
$data['monthly']['startdate'] = $key['startdate'];
$data['monthly']['enddate'] = $key['startdate'];
$data['monthly']['color'] = $key['color'];
$data['monthly']['starttime'] = 12;
$data['monthly']['endtime'] = 12;
$data['monthly']['url'] = "";
array_push($push_array, $data);
}
file_put_contents('../js/events.json', json_encode($push_array));
echo('<div class="alert alert-success resultsuccess" ><h4 class="alert-heading">Successful!</h4></div>');
}
} catch (Exception $e) {
echo('<div class="alert alert-danger resultsuccess" >'.'Error: '.$e->getMessage().'</div>');
}
I get that JSON format
[
{
"monthly":{
"id":"1",
"name":"test1",
"startdate":"2019-03-29",
"enddate":"2019-03-29",
"color":"#ffb128",
"starttime":12,
"endtime":12,
"url":""
}
},
{
"monthly":{
"id":"2",
"name":"test2",
"startdate":"2019-03-29",
"enddate":"2019-03-29",
"color":"#4263e6",
"starttime":12,
"endtime":12,
"url":""
}
}
]
Thanks for reading...
Your problem is that you are creating new arrays with a monthly index on each pass through your loop, instead of pushing the new data into the existing monthly array. Try this instead:
if ($res->rowCount() != 0) {
$push_array = array('monthly' => array());
$data = array();
foreach ($res as $key) {
$data['id'] = $key['id'];
$data['name'] = $key['name'];
$data['startdate'] = $key['startdate'];
$data['enddate'] = $key['startdate'];
$data['color'] = $key['color'];
$data['starttime'] = 12;
$data['endtime'] = 12;
$data['url'] = '';
array_push($push_array['monthly'], $data);
}

How to get sum of distinct key -> value in php arrays

I have the following string thatI convert into a json array. All I am trying to do put together keys with the same value for id_number and sum the amount to each of these keys and print the resulting value outside the loop.
$response = '{
"nhif":[
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T20:18:50"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T19:59:14"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:07:34"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:04:27"
},
{
"id_number":"12345678",
"amount":"5",
"date":"2018-09-14T09:04:21"
}
]
}';
$json_response = json_decode($response, true);
//Start NHIF
foreach ($json_response['nhif'] as $nhif) {
echo ''.$nhif{"id_number"}.' '.$nhif{"amount"}.' '.$nhif{"date"}.'<br/>';
}
//END NHIF
My expected output is:
#id_number #amount
AA112233 20
12345678 5
Any workaround this?
You can use array_reduce to sum the amount values by id_number:
$sums = array_reduce($json_response['nhif'], function ($c, $i) {
$c[$i['id_number']] = (isset($c[$i['id_number']]) ? $c[$i['id_number']] : 0) + $i['amount'];
return $c;
}, array());
print_r($sums);
Output:
AA112233 20
12345678 5
Demo on rextester
If you're using PHP7, this
isset($c[$i['id_number']]) ? $c[$i['id_number']] : 0
can be simplified to
$c[$i['id_number']] ?? 0
You can do solve this problem using an array
$response = '{
"nhif":[
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T20:18:50"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T19:59:14"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:07:34"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:04:27"
},
{
"id_number":"12345678",
"amount":"5",
"date":"2018-09-14T09:04:21"
}
]
}';
$json_response = json_decode($response, true);
$results = array(); // will map the unique keys with it's sum
//Start NHIF
foreach ($json_response['nhif'] as $nhif) {
if(!isset($results[$nhif['id_number']])) // new key initialized
$results[$nhif['id_number']] = $nhif['amount'];
else
$results[$nhif['id_number']] += $nhif['amount'];
}
//END NHIF
foreach($results as $key => $value) {
echo $key .' '.$value; // printing the result
}
Sort the array [If the data is not sorted otherwise do not need to sort].
Do the for loop and summation.
Try with this code sample, there are many other ways to solve this problem depending on problem solving skill.
$response = '{
"nhif":[
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T20:18:50"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T19:59:14"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:07:34"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:04:27"
},
{
"id_number":"12345678",
"amount":"5",
"date":"2018-09-14T09:04:21"
}
]
}';
$data = json_decode($response, true);
usort($data['nhif'], function($a, $b) {
return $b['id_number'] <=> $a['id_number'];
});
//Start NHIF
$amount = 0;
$id_number = null;
foreach($data['nhif'] as $nhif) {
if(($nhif['id_number'] != $id_number) && ($id_number != null)){
echo $id_number. "\t". $amount . "<br />";
$id_number = $nhif['id_number'];
$amount = $nhif['amount'];
}
else{
$id_number = $nhif['id_number'];
$amount = $amount + $nhif['amount'];
}
// echo ''.$nhif{"id_number"}.' '.$nhif{"amount"}.' '.$nhif{"date"}.'<br />';
}
echo $id_number. "\t". $amount . "<br />";
//END NHIF
You could create a new array for example $r and check if the key for $nhif['id_number'] already exists.
If it does, add value for $nhif['amount']using +=. If it does not, set the value using =
This example uses the ternary ?: operator:
$r = [];
foreach ($json_response['nhif'] as $nhif) {
isset($r[$nhif['id_number']]) ? $r[$nhif['id_number']] += $nhif['amount'] : $r[$nhif['id_number']] = $nhif['amount'];
}
Demo

Grouping JSON output according to specific mysql column

I have a mysql table (name:"messages") that has three columns as below:
messageID, fromUserID, content
I wish to have a json output using php script like following format; I need to seprate messages of each user (fromUserID column).
JSONOutput:
{
"newCount":"x",
"messages":
[
{
"fromUserID":"x",
"messagesArray":
[
{"messageID":"x","content":"xxx"},
{"messageID":"x","content":"xxx"},
{"messageID":"x","content":"xxx"}
]
},
{
"fromUserID":"y",
"messagesArray":
[
{"messageID":"x","content":"xxx"},
{"messageID":"x","content":"xxx"},
{"messageID":"x","content":"xxx"}
]
},
{
"fromUserID":"z",
"messagesArray":
[
{"messageID":"x","content":"xxx"},
{"messageID":"x","content":"xxx"},
{"messageID":"x","content":"xxx"}
]
}
]
}
My PHP Script:
$query = mysqli_query($con,"SELECT * FROM messages ORDER BY fromUserID");
$outputArray = array();
$outputArray['hasNew'] = mysqli_num_rows($query);
$messagesArray = array();
if($query)
{
while($row = mysqli_fetch_assoc($query))
{
$MSGArray = array();
$messagesArray['fromUserID'] = $row['fromUserID'];
$MSGArray['messageID'] = $row['messageID'];
$MSGArray['content'] = $row['content'];
$messagesArray['MessagesArray'][] = $MSGArray;
}
$outputArray['Messages'][] = $messagesArray;
}
echo json_encode($outputArray);
But with above script I give a wrong result as below:
{
"hasNew":6,
"Messages":
[
{
"fromUserID":"24",
"MessagesArray":
[
{"messageID":"4","content":"test"},
{"messageID":"3","content":"test"},
{"messageID":"6","content":"test"},
{"messageID":"5","content":"test"},
{"messageID":"1","content":"test"},
{"messageID":"2","content":"test"}
]
}
]
}
My PHP Script just using last fromUserID value to grouping messages !!!
Please let me know where I'm wrong ...
Try it
if($query)
{
while($row = mysqli_fetch_assoc($query))
{
$MSGArray = array();
$messagesArray[$row['fromUserID']]['fromUserID'] = $row['fromUserID'];
$MSGArray['messageID'] = $row['messageID'];
$MSGArray['content'] = $row['content'];
$messagesArray[$row['fromUserID']]['MessagesArray'][] = $MSGArray;
}
foreach($messagesArray as $value) {
$outputArray['Messages'][] = $value;
}
}

Multiple MySQL table to json_encode

I have 3 different tables in my database called consoleConsole, consoleModel, and consoleGame. Then what I want to do is that each console will have a loop inside for its models, and each models will have another loop inside for its games like this:
[
{
"Console":"PlayStation",
"Information":[
{
"Model":"PlayStation 3",
"Title":[
{
"Game":"007 Legends",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat: Assault Horizon",
"Publisher":"Namco"
}
]
},
{
"Model":"PlayStation 2",
"Title":[
{
"Game":"007: Agent of Fire",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat 4: Shattered Skies",
"Publisher":"Namco"
}
]
},
{
"Model":"PlayStation 1",
"Title":[
{
"Game":"007 Racing",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat",
"Publisher":"Namco"
}
]
}
]
},
{
"Console":"Wii",
"Information":[
{
"Model":"Wii",
"Title":[
{
"Game":"007: Quantum of Solace",
"Publisher":"Activision"
},
{
"Game":"AC/DC Live: Rock Band Track Rack",
"Publisher":"MTV Games"
}
]
}
]
},
{
"Console":"Xbox",
"Information":[
{
"Model":"Xbox",
"Title":[
{
"Game":"AFL",
"Publisher":"Acclaim"
},
{
"Game":"American Chopper",
"Publisher":"Activision"
}
]
},
{
"Model":"Xbox 360",
"Title":[
{
"Game":"AFL Live",
"Publisher":"Electronic Arts"
},
{
"Game":"Akai Katana Shin",
"Publisher":"Cave"
}
]
}
]
}
]
But sadly, I was not using my database with this one but instead I just wrote it straight in a php file.
EDIT
Anyways, moving on. I have modified my code and ended up like this.
<?PHP
$consoleQuery = "SELECT * ".
"FROM consoleConsole ".
"JOIN consoleModel ".
"ON consoleConsole.consoleId = consoleModel.consoleId ".
"JOIN consoleGame ".
"ON consoleModel.modelId = consoleGame.gameId";
$consoleResult = mysql_query($consoleQuery);
$consoleFields = array_fill_keys(array(
'consoleName',
), null);
$modelFields = array_fill_keys(array(
'modelName',
), null);
$console = array();
$rowConsole = array();
while ($rowConsole = mysql_fetch_assoc($consoleResult)) {
$consoleId = $rowConsole['consoleId'];
$modelId = $row['modelId'];
if (isset($console[$consoleId]['Information'])) {
$console[$consoleId]['Information'][] = array_intersect_key($rowConsole, $modelFields);
}
else {
$console[$consoleId] = array_intersect_key($rowConsole, $consoleFields);
$console[$consoleId]['Information'] = array(array_intersect_key($rowConsole, $modelFields));
}
}
$console = array_values($console);
echo json_encode($console);
?>
I was able to produce an output but it doesn't look like the output above.
[
{
"consoleName": "PlayStation",
"Information": [
{
"modelName": "PlayStation"
},
{
"modelName": "PlayStation 2"
},
{
"modelName": "PlayStation 3"
},
{
"modelName": "PlayStation 3"
}
]
},
{
"consoleName": "Wii",
"Information": [
{
"modelName": "Wii"
},
{
"modelName": "Wii"
}
]
},
{
"consoleName": "Xbox",
"Information": [
{
"modelName": "Xbox"
},
{
"modelName": "Xbox 360"
}
]
}
]
Their relations:
What my problem is right now, I can't add the Title of the each Game.
Ok so I have written up your solution. You have to be sure that the order by is included there because it assumes that you are ordering them with there items together. I also didnt know how your publisher was stored so I separated that out into a separate table (this will allow you to then get items by just there publisher as well), which is now 4 joins. Also on another note I have updated it to do inner joins as well. This way you will not get empty results for consoles that don't have any games assigned to them. If you want these you could simply change the joins so that it would give you those results as well. Let me know if this helps
//get all of the information
$query = '
SELECT c.consoleId,c.consoleName,m.modelId,m.modelName,g.gameId,g.gameName,p.publisherId,p.publisherName
FROM `consoleconsole` c
INNER JOIN `consolemodel` m ON c.consoleId=m.consoleId
INNER JOIN `consolegame` g ON m.modelId=g.modelId
INNER JOIN `consolepublisher` p ON g.publisherId = p.publisherId
ORDER BY c.consoleName, m.modelName, g.gameName
';
//get the results
$result = mysql_query($query);
//setup array to hold information
$consoles = array();
//setup holders for the different types so that we can filter out the data
$consoleId = 0;
$modelId = 0;
//setup to hold our current index
$consoleIndex = -1;
$modelIndex = -1;
//go through the rows
while($row = mysql_fetch_assoc($result)){
if($consoleId != $row['consoleId']){
$consoleIndex++;
$modelIndex = -1;
$consoleId = $row['consoleId'];
//add the console
$consoles[$consoleIndex]['console'] = $row['consoleName'];
//setup the information array
$consoles[$consoleIndex]['information'] = array();
}
if($modelId != $row['modelId']){
$modelIndex++;
$modelId = $row['modelId'];
//add the model to the console
$consoles[$consoleIndex]['information'][$modelIndex]['model'] = $row['modelName'];
//setup the title array
$consoles[$consoleIndex]['information'][$modelIndex]['title'] = array();
}
//add the game to the current console and model
$consoles[$consoleIndex]['information'][$modelIndex]['title'][] = array(
'game' => $row['gameName'],
'publisher' => $row['publisherName']
);
}
echo json_encode($consoles);
Since you are using php function to encode json , it will give you the json in its default format. what you have to do is create your own function using string manipulation to get desired result.

Categories