Having trouble building nested JSON with PHP - php

I am having trouble getting these arrays to nest properly. I am grabbing all the rows from a SQL database and building an array to output in JSON for my crud app. One category has been easy, but the client now wants subcategories and that's when I hit a major wall. I am trying to nest these subcategories into categories. I can do either, but am failing to get them working together. The following is my PHP code:
while ($row = $query->fetch_assoc()) {
$categories[$row['category']][] = array(
$row['subcategory'] => $subcategories[$row['subcategory']][] = array(
'id' => $row['id'],
'item_name' => $row['item_name'],
'description' => $row['description'],
'price' => $row['price'],
),
);
}
foreach ($categories as $key => $value) {
$category_data[] = array(
'category' => $key,
'category_list' => $value,
);
}
foreach ($subcategories as $key => $value) {
$subcategory_data[] = array(
'subcategory' => $key,
'subcategory_list' => $value,
);
}
When I json_encode($category_data) I get the following JSON:
[
{
"category": "Beer",
"category_list": [
{
"Draft Beer": {
"id": "1",
"item_name": "Yuengling",
"description": "Lager. Pottstown, Pa. An American classic."
}
},
{
"Draft Beer": {
"id": "6",
"item_name": "Bud Light",
"description": "American Light Lager"
}
},
{
"Domestic Bottles": {
"id": "9",
"item_name": "Stone IPA",
"description": "India Pale Ale.<em> Escondido, Colo."
}
}
]
},
{
"category": "Wine",
"category_list": [...]
}
]
Which might work, but I would like it to join the like keys (ie: Draft Beer) into the same array. It does do that when I json_encode($subcategory_data) as shown below, but its not separated into categories, just the subcategories.
[
{
"subcategory": "Draft Beer",
"subcategory_list": [
{
"id": "1",
"item_name": "Yuengling",
"description": "Lager. Pottstown, Pa."
},
{
"id": "6",
"item_name": "Bud Light",
"description": "American Light Lager. Milwaukee, Wisc."
}
]
},
{
"subcategory": "Red Wine",
"subcategory_list": [
{
"id": "17",
"item_name": "Kendall-Jackson",
"description": "Cabernet Sauvignon, 2010."
},
{
"id": "18",
"item_name": "Sanford",
"description": "Pinot Noir, 2011. Lompoc, Calif"
}
]
},
{
"subcategory": "Domestic Bottles",
"subcategory_list": [
{
"id": "9",
"item_name": "Stone IPA",
"description": "India Pale Ale. Escondido, Colo."
},
{
"id": "10",
"item_name": "Blue Moon",
"description": "Belgian-style Wheat Ale."
}
]
}
]
So my question is why does it merge in the second set of data but not the first. How do I get the subcategory_data into the category_data. Any help id truly appreciated. Below is an example if what I am looking for:
{
"category_name":"Beer",
"category_list" : [
{
"subcategory_name": "Draft Beer",
"subcategory_list": [
{
"id": "1",
"item_name": "Yuengling",
"description": "Lager. Pottstown, Pa."
},
{
"id": "6",
"item_name": "Bud Light",
"description": "American Light Lager. Milwaukee, Wisc."
}
}
]
},
{
"category_name":"Wine",
"category_list" : [
{
"subcategory_name": "Red Wine",
"subcategory_list": [...]
}
]
}
Thanks for looking, I am fairly new to PHP and am relying on my javascript skills.

First, try var_dump($categories). You'll see that you're building a rather weird data structure (you have arrays of 1-element arrays...). The following code will build a simpler structure:
$categories[$row['category']][$row['subcategory']][] = array(
'id' => $row['id'],
'item_name' => $row['item_name'],
'description' => $row['description'],
'price' => $row['price'],
);
This will serialize to JSON that's probably acceptable as is:
{
"Beer": {
"Draft Beer": [
{
"id": "1",
"item_name": "Yuengling",
"description": "Lager. Pottstown, Pa."
},
{
"id": "6",
"item_name": "Bud Light",
"description": "American Light Lager. Milwaukee, Wisc."
}
],
...
An additional transformation gets the data in the format you asked for:
foreach ($categories as $category_name => $subcategories) {
$subcategory_data = array();
foreach ($subcategories as $subcategory_name => $items) {
$subcategory_data[] = array(
'subcategory_name' => $subcategory_name,
'subcategory_list' => $items
);
}
$category_data[] = array(
'category_name' => $category_name,
'category_items' => $subcategory_data
);
}

Related

Printing a foreach loop in a loop maintaining json

I have this code as I am trying to implement a json code using foreach loop
foreach ($single_google as $row) {
$data['step'][] = array(
"#type" => "HowToStep",
"url" => "https://example.com/kitchen#step1",
"name" => "Prepare the surfaces",
"itemListElement" => array(),
"image" => [
"#type" => "ImageObject",
"url" => "https://example.com/photos/1x1/photo-step1.jpg",
"height" => "406",
"width" => "305"
],
);
$all_step_google = json_decode($row["steps"]);
foreach ($all_step_google as $single_step_google) {
$data['itemListElement'][] = array(
"#type" => "HowToDirection",
"text" => "testing",
);
}
}
print_r(json_encode($data));
at the end of the coding, trying to run it I got this
{
"#type": "HowToStep",
"url": "https://example.com/kitchen#step1",
"name": "Prepare the surfaces",
"itemListElement": [],
"image": {
"#type": "ImageObject",
"url": "https://example.com/photos/1x1/photo-step1.jpg",
"height": "406",
"width": "305"
}
}
],
"itemListElement": [
{
"#type": "HowToDirection",
"text": "test."
}
instead of this which I needed actually.
{
"#type": "HowToStep",
"url": "https://example.com/kitchen#step1",
"name": "Prepare the surfaces",
"itemListElement": [
{
"#type": "HowToDirection",
"text": "Test"
}
],
"image": {
"#type": "ImageObject",
"url": "https://example.com/photos/1x1/photo-step1.jpg",
"height": "406",
"width": "305"
}
}
],
I want the "itemListElement" => array(), to print before the "image" => [] but it kept printing after the foreach loop. Please help me, am getting lost.
You use $data['itemListElement'][] = array(... on your second loop so that will assign new key to your data master array instead, the right code should be like this
............
foreach ($all_step_google as $key => $single_step_google) {
$data['step'][$key]['itemListElement'][] = array(
"#type" => "HowToDirection",
"text" => "testing",
);
}
............

incorrect JSON data - Array to Object

I am new in php json object.
I am trying to create below json format from my database table data. Where basically Visits is an object. But my object knowledge i very limited so I am stuck into it.
"visits": {
"order_1": {
"location": {
"name": "6800 Cambie",
"lat": 49.227107,
"lng": -123.1163085
},
"start": "9:00",
"end": "12:00",
"duration": 10,
"load": 1,
"type": "A",
"priority": "high"
}
}
But I am getting below json format. Which is wrong.
{
"visits": [
{
"order_1": {
"location": {
"name": "21 Marara Court, ALBANY CREEK QLD 4035",
"lat": "-37.7044",
"lng": "145.1006"
}
}
},
{
"order_2": {
"location": {
"name": "Unit 7, 19 O'Connell Street, KANGAROO POINT QLD 4169",
"lat": "-37.6389",
"lng": "145.1950"
}
}
},
],
"fleet": {
"vehicle_1": {
"start_location": {
"id": "depot",
"name": "23 Moverly Rd",
"lat": -33.9356141,
"lng": 151.2425993
},
"end_location": {
"id": "depot",
"name": "23 Moverly Rd",
"lat": -33.9356141,
"lng": 151.2425993
}
}
},
}
The problem is on "visits": [ array. But I need object.
So my php code is below:
foreach ($orders as $value) {
$orders2[] = array(
"order_$i"=> array(
"location"=> array(
"name"=> $value['address'],
"lat"=> $value['lat'],
"lng"=> $value['long']
),
),
);
}
$data = array(
"visits" => $orders2,
"fleet"=> array(
"vehicle_1"=> array(
"start_location"=> array(
"id"=> "depot",
"name"=> "23 Moverly Rd",
"lat"=> -33.9356141,
"lng"=> 151.2425993
),
"end_location"=> array(
"id"=> "depot",
"name"=> "23 Moverly Rd",
"lat"=> -33.9356141,
"lng"=> 151.2425993
),
)
),
);
It would be better if anyone can give me any idea. Thank you :)
To get an object with json_encode you have to use custom array keys.
Try this:
foreach ($orders as $value) {
$orders2["order_$i"] = array(
"location"=> array(
"name"=> $value['address'],
"lat"=> $value['lat'],
"lng"=> $value['long']
),
);
}
Just for the sake of completeness:
You can also use the JSON_FORCE_OBJECT option in json_encode or directly use a StdClass to force it to get an json object. But in your case the structure was wrong anyway, so the code above should work fine for you.

how I do Multidimensional foreach loop array to json object conversion in php

I am working on the array to JSON object code and want the output using json_encode method.
here is the code
foreach($servicecategory as $servicecategory1) {
$getcat = $objcat->Get_Category($servicecategory1);
$employee = array(
'category_id'=>mysql_real_escape_string($getcat['id']),
'category_name'=>mysql_real_escape_string($getcat['catname']),
'category_image_url'=>"",
'subcategory'=>array()
);
$getsubcat = $objcat->getCategoriesAdminNew($servicecategory1);
foreach($getsubcat as $getsubcat1) {
$getcat = $objcat->Get_Category($getsubcat1['id']);
$employee['subcategory'][]= array(
'category_id'=>mysql_real_escape_string($getcat['id']),
'category_name'=>mysql_real_escape_string($getcat['catname']),
'vendor_products_details' =>array()
);
$getproduct = $objuser->VendorProductDetailsNew2($userinfo['profile_id'],$getcat['id']);
foreach($getproduct as $getproducts){
$getcat = $objcat->Get_Category($getproducts['subcat_id']);
$employee['vendor_products_details'][] = array(
'product_id' => $getproducts['id'],
'product_name' => $getproducts['pname'],
'Price' => $getproducts['price'],
);
}
}
$data[] = $employee;
}
if($userinfo!='') {
$infodatas=array("status"=>"success","vendor_detail"=> array($array1, $data));
$ress=json_encode($infodatas);
echo $ress ;
}
it displays the output like below, which is not the proper format for json out put.
{
"category_id": "1",
"category_name": "Dry Cleaning",
"category_image_url":"",
"subcategory": [
{
"sub_category_id": "4",
"sub_category_name": "Men",
"vendor_products_details": [
]
},
{
"sub_category_id": "5",
"sub_category_name": "Women",
"vendor_products_details": [
]
}
],
"vendor_products_details": [
{
"product_id": "19",
"product_name": "T Shirt",
"Price": "20"
},
{
"product_id": "20",
"product_name": "Top",
"Price": "15"
}
]
},
But I want the output in below format using multiple for each loop.
{
"category_id": "1",
"category_name": "Dry Cleaning",
"category_image_url": "",
"subcategory": [
{
"sub_category_id": "4",
"sub_category_name": "Men",
"vendor_products_details": [
{
"product_id": "19",
"product_name": "T Shirt",
"Price": "20"
},
{
"product_id": "20",
"product_name": "Top",
"Price": "15"
}
]
},
{
"sub_category_id": "5",
"sub_category_name": "Men",
"vendor_products_details": "Women",
"vendor_products_details": [
{
"product_id": "18",
"product_name": "T shirt",
"Price": "15"
},
{
"product_id": "9",
"product_name": "Bedsheet",
"Price": "15"
}
]
}
]
},
same for each main category
Your current foreachloop states that in the get products section it should be added to $employee['vendor_products_details'][], but your explanation states that you want the products to be under your subcategory. This can be achieved by 2 small changes:
foreach($getsubcat as $getsubcat1) {
$getcat = $objcat->Get_Category($getsubcat1['id']);
$employee['subcategory'][$getsubcat1['id']]= array(
'category_id'=>mysql_real_escape_string($getcat['id']),
'category_name'=>mysql_real_escape_string($getcat['catname']),
'vendor_products_details' =>array()
);
$getproduct = $objuser->VendorProductDetailsNew2($userinfo['profile_id'],$getcat['id']);
foreach($getproduct as $getproducts){
$getcat = $objcat->Get_Category($getproducts['subcat_id']);
$employee['subcategory'][$getsubcat1['id']]['vendor_products_details'][] = array(
'product_id' => $getproducts['id'],
'product_name' => $getproducts['pname'],
'Price' => $getproducts['price'],
);
}
}
What is changed:
In your foreachloop with $getsubcat you need to changed the array to:
$employee['subcategory'][$getsubcat1['id']]= array(............);
In your foreachloop with $getproduct you need to change the array to:
$employee['subcategory'][$getsubcat1['id']]['vendor_products_details'][] = array(............);
Doing it this way you vendor product details will be nested in your subcategory with the id used in that specific loop.

PHP - Moving a key within an array and flatten it

I have this array of object:
[
{
"id": 1,
"name": "Carbo",
"menus": [
{
"id": 33,
"name": "FloralWhite",
"image": {
"web": "https://lorempixel.com/640/360/food/?89722",
"mobile": "https://lorempixel.com/640/360/food/?89722",
"square": "https://lorempixel.com/640/360/food/?89722"
},
"logs": {
"price": 2
}
},
{
"id": 40,
"name": "LightGray",
"image": {
"web": "https://lorempixel.com/640/360/food/?63930",
"mobile": "https://lorempixel.com/640/360/food/?63930",
"square": "https://lorempixel.com/640/360/food/?63930"
},
"logs": {
"price": 2
}
},
]
}
]
What I want to achieve:
[
{
"id": 1,
"name": "Carbo",
"menus": [
{
"id": 33,
"name": "FloralWhite",
"image": {
"web": "https://lorempixel.com/640/360/food/?89722",
"mobile": "https://lorempixel.com/640/360/food/?89722",
"square": "https://lorempixel.com/640/360/food/?89722"
},
"price": 2
},
{
"id": 40,
"name": "LightGray",
"image": {
"web": "https://lorempixel.com/640/360/food/?63930",
"mobile": "https://lorempixel.com/640/360/food/?63930",
"square": "https://lorempixel.com/640/360/food/?63930"
},
"price": 2
},
]
}
]
I've tried using laravel collection flatten with depth but it fail
$data = collect($data->menus);
$data = $data->flatten(1);
$data->values()->all();
How can I flatten the menus['logs'] object so it can one level with menu?
Something like this should do the trick. Simply iterate over your array, set the new property and remove the one you don't want.
$data = json_decode("[{
\"id\": 1,
\"name\": \"Carbo\",
\"menus\": [
{
\"id\": 33,
\"name\": \"FloralWhite\",
\"image\": {
\"web\": \"https://lorempixel.com/640/360/food/?89722\",
\"mobile\": \"https://lorempixel.com/640/360/food/?89722\",
\"square\": \"https://lorempixel.com/640/360/food/?89722\"
},
\"logs\": {
\"price\": 2
}
},
{
\"id\": 40,
\"name\": \"LightGray\",
\"image\": {
\"web\": \"https://lorempixel.com/640/360/food/?63930\",
\"mobile\": \"https://lorempixel.com/640/360/food/?63930\",
\"square\": \"https://lorempixel.com/640/360/food/?63930\"
},
\"logs\": {
\"price\": 2
}
}
]
}]");
foreach($data as $val){
foreach($val->menus as $menuVal){
$menuVal->price = $menuVal->logs->price;
unset($menuVal->logs);
}
}
#Stefen Suhat i really don't know what is the syntax for laravel but i did it with a simple php foreach() hope this will help you, as your array's depth is long so i had gone to all the levels of your array, check code and output snippet here https://eval.in/806879
try below one:
<?php
$array = array(
array(
"id"=> 1,
"name"=> "Carbo",
"menus"=> array(
array(
"id"=> 33,
"name"=> "FloralWhite",
"image"=> array(
"web"=> "https=>//lorempixel.com/640/360/food/?89722",
"mobile"=> "https=>//lorempixel.com/640/360/food/?89722",
"square"=> "https=>//lorempixel.com/640/360/food/?89722"
),
"logs"=> array(
"price"=> 2
)
),
array(
"id"=> 40,
"name"=> "LightGray",
"image"=> array(
"web"=> "https=>//lorempixel.com/640/360/food/?63930",
"mobile"=> "https=>//lorempixel.com/640/360/food/?63930",
"square"=> "https=>//lorempixel.com/640/360/food/?63930"
),
"logs"=> array(
"price"=> 2
)
),
)
)
);
foreach($array as $key => $value){
foreach ($value as $key1 => $value1) {
if(is_array($value1) && $key1 == "menus"){
foreach($value1 as $key2 => $value2) {
foreach ($value2 as $key3 => $value3) {
if(is_array($value3) && $key3 == "logs"){
unset($array[$key][$key1][$key2][$key3]);
$array[$key][$key1][$key2] = array_merge($array[$key][$key1][$key2], $value3);
}
}
}
}
}
}
echo "array after<br>";
echo "<pre>";
print_r($array); //your array after
?>

Creating array inside array from mysql data to json

I am trying to create json with php from two mysql tables:- Category(unique)- Subcategories or Rights(multiple in same category)But I can't list multiple subcategories under one category. Instead, for every subcategory new set of results is made that contains category data also.
This is php code:
$sql = "SELECT a.id as rid,a.name as rname,a.img as rimg,a.price,b.id as cid,b.name as cname FROM rights a INNER JOIN categories b ON a.category=b.id";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
$json_response = array();
while($row = $result->fetch_assoc()) {
$row_array['idCategory'] = $row['cid'];
$row_array['nameCategory'] = $row['cname'];
$row_array['rights'] = array([
'idRight' => $row['rid'],
'name' => $row['rname'],
'price' => $row['price'],
'image' => $row['rimg']
]);
array_push($json_response,$row_array);
}
echo json_encode($json_response);
}
With this I am getting:
[{
"idCategory": "1",
"nameCategory": "Cat1",
"rights": [{
"idRight": "1",
"name": "Right1 in Cat1",
"price": "10",
"image": "img1.jpg"
}]
}, {
"idCategory": "2",
"nameCategory": "Cat2",
"rights": [{
"idRight": "2",
"name": "Right1 in Cat2",
"price": "20",
"image": "img2.jpg"
}]
}, {
"idCategory": "2",
"nameCategory": "Cat2",
"rights": [{
"idRight": "3",
"name": "Right2 in Cat2",
"price": "30",
"image": "img3.jpg"
}]
}]
I tried changing mysql select with GROUP_CONCAT and GROUP BY but then I get data in one row like this:
"rights": [{
"idRight": "2,3",
"name": "Right1 in Cat2,Right2 in Cat2",
"price": "20,30",
"image": "img2.jpg,img3.jpg"
}]
But I need it like this:
[{
"idCategory": "1",
"nameCategory": "Cat1",
"rights": [{
"idRight": "1",
"name": "Right1 in Cat1",
"price": "10",
"image": "img1.jpg"
}]
}, {
"idCategory": "2",
"nameCategory": "Cat2",
"rights": [{
"idRight": "2",
"name": "Right1 in Cat2",
"price": "20",
"image": "img2.jpg"
},
{
"idRight": "3",
"name": "Right2 in Cat2",
"price": "30",
"image": "img3.jpg"
}]
}]
How to achieve that?
You need to remap your array and then initialize an array for the rights key... so, change your while loop something like this:
$json_response = array();
while($row = $result->fetch_assoc()) {
if (!isset($json_response[ $row['idCategory'] ])) {
$json_response[ $row['idCategory'] ] = [
'idCategory' => $row['idCategory'],
'nameCategory' => $row['nameCategory'],
'rights' => [],
];
}
$json_response[ $row['idCategory'] ]['rights'][] = [
'idRight' => $row['rid'],
'name' => $row['rname'],
'price' => $row['price'],
'image' => $row['rimg']
];
}
// We want the final result to ignore the keys and to create a JSON array not a JSON object
$data = [];
foreach ($json_response as $element) {
$data[] = $element;
}
echo json_encode($data);
This part of the code $json_response[ $row_array['idCategory'] ] helps to maintain a unique grouping of the data because it creates a hash based on the idCategory. An array can only have one key and since idCategory is always unique we can use that as the key for grouping on.
Then because we now have a hash-based array, we have to create a new array that is a 'real' array for when it is converted to JSON.
You do not want to use GROUP BY or GROUP_CONCAT in this situation.
I revised the code above to fit my needs, but I am having trouble to make another array of that array...
from:
...
$json_response[ $row['idCategory'] ]['rights'][] = [
'idRight' => $row['rid'],
'name' => $row['rname'],
'price' => $row['price'],
'image' => $row['rimg']
];
to:
$json_response[ $row['regCode'] ]['provinces'][] = $row['provDesc'];
actually this is a follow up question,
how about array inside array of that array...
like this:
[
{
rid: "1",
region: "REGION I", //array 1
provinces: [
{
pid: "128",
province: "ILOCOS NORTE", //array 2
cities[
"Adams", //array 3
"Bacarra"
],
"ILOCOS SUR"
]
},
{
rid: "2",
region: "REGION II",
provinces: [
"BATANES",
"CAGAYAN"
]
}
]

Categories