PHP JSON add array - php

i need some assistance with properly generating JSON. I almost have it, but I need to have each category and its related item in its own array. I have multiple categories each with many items under them. My JSON looks good, i just need the categories as an array along with its items. Any help is greatly appreciated!
Here is my code:
$channel ['items']['post']['categories'][$category_name]['details'][] = array(
'title' => $title,
'price' => $price,
'date_time' => $date_time,
'description' => $description,
);
}
$channels = array($channel);
$json = json_encode($channel);
header('Content-type: application/json');
echo $json;
My JSON looks like this currently:
{
"items": { /// THIS IS MEANT TO ORGANIZE UNDER ITEMS
"post": { ///THIS IS PROBABLY UNNECESSARY, I JUST HAVEN'T REMOVED IT.
"categories": {
"Baby": { ///I HAVE MANY MANY CATEGORIES
"details": [ ///I HAVE MANY MANY ITEMS UNDER EACH CATEGORY
{
"title": "trying with category id again",
"price": "3344.55",
"date_time": "2013-11-11 17:33:49",
"description": "Descriptor sb ",
"category_id": "3",
},
]
But I want it to look like this:
{
"items": {
"categories": [{ /// NEED THE BRACKET HERE
"Baby": {
"details": [
{
"title": "trying with category id again",
"price": "3344.55",
"date_time": "2013-11-11 17:33:49",
"description": "Descriptor sb ",
},
{
"title": "what the",
"price": "44444.66",
"date_time": "2013-11-18 20:15:58",
"description": "Blah blah",
},
]
},
"Baby Stuff": {
"details": [
{
"title": "putting in title",
"price": "3000.99",
"date_time": "2013-11-11 17:42:15",
"description": "Blah blah blah",
},
{
"title": "adding another listing",
"price": "400000.99",
"date_time": "2013-11-17 22:37:02",
"description": "Blah blah blah",
},
]
},
"More Baby Stuff": {
"details": [
{
"title": "does this work",
"price": "4000.77",
"date_time": "2013-11-18 19:59:49",
"description": "Description ",
},
{

Add another [] after ['categories'] and that should do the trick
$channel ['items']['post']['categories'][][$category_name]['details'][] = array( // ...
$channel ['items']['post']['categories'][]['Baby']['details'][] = array(
'title' => 'trying with category id again',
'price' => 3344.55,
'date_time' => '2013-11-11 17:33:49',
'description' => 'Descriptor sb',
);
$channels = array($channel);
$json = json_encode($channel);
echo $json;
Output
{
"items": {
"post": {
"categories": [
{
"Baby": {
"details": [
{
"title": "trying with category id again",
"price": 3344.55,
"date_time": "2013-11-11 17:33:49",
"description": "Descriptor sb"
}
]
}
}
]
}
}
}
See it working here on ideone

Based on comments and edits to OP, perhaps you should be looking at a data structure like this:
{
"categories":
[
{
"category_name": "Baby",
... [Other category metadata],
"category_items":
[
{
"item_name": "Item Name",
... [Other item information]
},
{ [next item] },
...
]
},
{ [ next category ] },
...
]
}
This means one might build this object in similar manner to the following (assuming for example you are building this from DB query):
$channel = new stdClass();
$channel->categories = array();
LOOP for categories as $category
$category = new stdClass();
$category->category_name = 'some value';
$category->some_other_category_metadata = 'some other value';
$category->category_items = array();
INNER LOOP on items in category as $item
$item = new stdClass();
$item->item_name = 'item name';
$item->some_other_item_data = 'data';
$category->category_items[] = $item;
END INNER LOOP
$channel->categories[] = $category;
END OUTER LOOP
json_encode($channel);

Related

Put 2 objects inside the object

I'm writing some queries and receiving the $help_articles:
[
{
"id": 10,
"title": "Creative Agency Creation",
"sub_title": "Learn how to create creative agency and setup information and users",
"featured_image": image.jpg",
"content": "[{some content}]",
},
{
"id": 12,
"title": "Create New User",
"sub_title": "Instruction to create new user",
"featured_image": "56095569_step_3.jpg",
"content": "[{some_content}]",
}
]
Another query is returning $related_articles
[
{
"title": "Creative Agency Creation",
"slug": "creative-agency-creation"
},
{
"title": "Create New User",
"slug": "create-new-user"
},
]
I need 2 put this 2 objects in 1 like this:
{
"all_articles": [
{
"id": 10,
"title": "Creative Agency Creation",
"sub_title": "Learn how to create creative agency and setup information and users",
"featured_image": image.jpg",
"content": "[{some content}]",
},
{
"id": 12,
"title": "Create New User",
"sub_title": "Instruction to create new user",
"featured_image": "56095569_step_3.jpg",
"content": "[{some_content}]",
}
],
"related_articles": [
{
"title": "Creative Agency Creation",
"slug": "creative-agency-creation"
},
{
"title": "Create New User",
"slug": "create-new-user"
},
]
}
I'm making the following:
$final = new \stdClass();
$final=$help_articles;
$final['related_articles'] = $related_articles;
return response()->json($final);
But I didn't get the required result.
Please advice, what I'm doing wrong and how to fix this
#Cbroe, thanks a lot, it's helped.
The solution was simple:
$final = [
'all_articles' => $help_articles,
'related_articles' => $related_articles
];
return response()->json($final);
What about compact()? It was like
$all_articles = []; //some array
$related_articles = []: //some data
return response()->json(compact(['all_articles', 'related_articles']));
Try this it will work in your case.
$final = new stdClass();
$final->all_articles = $all_articles;
$final->related_articles = $related_articles;
return response()->json($final);

Format the json encode just like on laravel php

Supposed I have a query that gets the image from a certain tweet
[
{
"pic": "/upload/15680712995mb.jpg",
"tweet_id": "48"
},
{
"pic": "/upload/1568071299test.PNG",
"tweet_id": "48"
},
{
"pic": "/upload/1568015310test.PNG",
"tweet_id": "47"
}
]
And I have a result also from a query that gets all of the tweet
[
{
"id": "48",
"tweet": "test",
},
{
"id": "47",
"tweet": "test tweet",
},
{
"id": "45",
"tweet": "test tweet 3",
}
]
How can I format the result like this (Just like on laravel)
[
{
"id": "48",
"tweet": "test",
"pics": [
[
"/upload/15680712995mb.jpg"
],
[
"/upload/1568071299test.PNG"
],
]
},
{
"id": "47",
"tweet": "test tweet",
"pics" : [
[
"/upload/1568015310test.PNG"
]
]
},
{
"id": "45",
"tweet": "test tweet 3",
"pics" : []
}
]
And this is my simplified code
public function getTweets()
{
$pics = $this->model->getPics();
$aTweets = $this->model->getTweets();
$map = [];
$props = [];
foreach ($aTweets as $sTweet) {
$map['id'] = $sTweet['id'];
$map['tweet'] = $sTweet['tweet'];
foreach ($pics as $pic) {
if ($pic['id'] === $sTweet['tweet_id']) {
$map['pics'] = [$pic['pic']];
}
}
$props[] = $map;
}
return $props;
}
but it just gives me the following output
{
"id": "48",
"tweet": "test",
"pics": [
"/upload/1568015310test.PNG"
]
},
{
"id": "47",
"tweet": "test tweet",
"pics": [
"/upload/1568015310test.PNG"
]
},
Any idea how can I format the result. thanks in advance.?
I'm not sure what's troubling you but in order to add multiple values inside, just put another nesting like what I've eluded in the comments section:
$map['pics'][] = $pic['pic'];
// ^
So to complete the answer:
$map = [];
$props = [];
foreach ($aTweets as $sTweet) {
$map['id'] = $sTweet['id'];
$map['tweet'] = $sTweet['tweet'];
$map['pics'] = []; // initialize
foreach ($pics as $pic) {
if ($pic['tweet_id'] === $sTweet['id']) {
$map['pics'][] = [$pic['pic']];
}
}
$props[] = $map;
}
This essentially creates another dimension for pics index as an array and continually pushing, provided they have the same ID.
Sidenote: tweet_id is to pics and id is to aTweets. Your's have the other way around.

Group and reformat an array of objects in PHP

I have the following performance problem in PHP code. An external API that I cannot edit, returns a JSON array like this one:
[{"name": "Name 1", "code": "Code 1", "attribute1": "Black", "attribute2": "32", "price": "10"},
{"name": "Name 2", "code": "Code 2", "attribute1": "Yellow", "attribute2": "", "price": "15"},
{"name": "Name 1", "code": "Code 3", "attribute1": "Yellow", "attribute2": "32", "price": "20"},....
]
I want to group this by name and reformat it to a JSON array like this:
[{
"name": "Name 1",
"available_attributes": [ "size", "color" ],
"variations": [
{ "attributes": { "size": "32", "color": "Black" }, "price": "10", "code": "Code 1"},
{ "attributes": { "size": "32", "color": "Yellow" }, "price": "20", "code": "Code 3"}
]
}, {
"name": "Name 2",
"available_attributes": [ "color" ],
"variations": [ { "attributes": { "color": "Yellow" }, "price": "15", "code": "Code 2"}]
}]
My solution is ugly and time-consuming since I used a simple brute force to iterate on the response and then again every time on the array to update the one I have already there.
So, I am looking for a solution focused on performance and speed.
Edit. This is my code. The only difference is that in case of both attributes being empty, instead of the variations and available_attributes arrays, it has the price and the sku only.
function cmp( $a, $b ) {
if ( $a['name'] == $b['name'] ) {
return 0;
}
return ( $a['name'] < $b['name'] ) ? - 1 : 1;
}
function format_products_array($products) {
usort( $products, "cmp" );
$formatted_products = array();
$new = true;
$obj = array();
for ( $i = 0; $i < count( $products ); $i++ ) {
if ( $new ) {
$obj = array();
$attr = array();
$obj['available_attributes'] = array();
$obj['variations'] = array();
$obj['name'] = $products[$i]['name'];
if ( $products[$i]['attribute1'] != '' ) {
array_push( $obj['available_attributes'], 'color' );
$attr['color'] = $products[$i]['attribute1'];
}
if ( $products[$i]['attribute2'] != '' ) {
array_push( $obj['available_attributes'], 'size' );
$attr['size'] = $products[$i]['attribute2'];
}
}
if ( $products[ $i ]['name'] == $products[ $i + 1 ]['name']) {
$new = false;
$attr['size'] = $products[$i]['attribute2'];
$attr['color'] = $products[$i]['attribute1'];
if ( empty($obj['available_attributes']) ) {
$obj['price'] = $products[$i]['price'];
} else {
$var = array();
$var['price'] = $products[$i]['price'];
$var['code'] = $products[$i]['code'];
$var['attributes'] = $attr;
array_push($obj['variations'], $var);
}
} else {
$new = true;
if ( empty($obj['available_attributes']) ) {
$obj['price'] = $products[$i]['price'];
}
$attr['size'] = $products[$i]['attribute2'];
$attr['color'] = $products[$i]['attribute1'];
$var['attributes'] = $attr;
array_push($obj['variations'], $var);
array_push($formatted_products, $obj);
}
}
return $formatted_products;
}
A faster solution is when generating the array to store the unique identifies or each object eg to generate:
[
"Name1":{
"name": "Name 1",
"code": "Code 1",
"available_attributes": [ "size", "color" ],
"variations": [
{ "attributes": { "size": "32", "color": "Black" }, "price": "10"},
{ "attributes": { "size": "32", "color": "Yellow" }, "price": "20"}
]
},
"Name2": {
"name": "Name 2",
"code": "Code 2",
"available_attributes": [ "color" ],
"variations": [ { "attributes": { "color": "Yellow" }, "price": "15"}]
}]
OR
[
"Code 1":{
"name": "Name 1",
"code": "Code 1",
"available_attributes": [ "size", "color" ],
"variations": [
{ "attributes": { "size": "32", "color": "Black" }, "price": "10"},
{ "attributes": { "size": "32", "color": "Yellow" }, "price": "20"}
]
},
"Code 2": {
"name": "Name 2",
"code": "Code 2",
"available_attributes": [ "color" ],
"variations": [ { "attributes": { "color": "Yellow" }, "price": "15"}]
}]
Afterwards (optionally)remove any association.
Afterwards you may store them in a memcached/redis then when you need to re-retrieve the same data then just look in redis/memcached first.
So it may be time consuming at first but afterwards it will be ready to do that so they will be only on "unlucky" guy/girl who will do the very same thing.
In case it is extreemely time consuming loops then use a worker to generate theese data ans store them in an document-based storage such as mongodb/couchdb afterwards the site will look on the ready made document.

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"
]
}
]

Having trouble building nested JSON with 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
);
}

Categories