Seperate treatment of last/first entry in loop (that has a subloop) - php

I have some troubles with the following situation. I want to output nested information that looks a bit like this:
"name": "X",
"children": [
{
"name": "categories",
"children": [
{
"name": "Cat A",
"children": [
{"name": "B"},
{"name": "C"},
{"name": "D"}
]
},
{
"name": "Cat B",
"children": [
{"name": "C"},
{"name": "D"}
]
}
In this case you see that the last } of child Cat A has an comma at the end, while the last nest (Cat B) does not have comma at the end. In a previous topic I learned how to resolve the comma within the the inner loop ({"name": "D"}). However, using the implode (with sprintf instead of printf) at the end of the first while loop (see code below) created double prints of the data.
This is what the code looks like (slightly adjusted):
while ($ucs = mysqli_fetch_object($uc))
{
printf('{');
printf('"name": "%s",', $ucs->cat);
/*for ($i = 0; $i < 100; $i++)
{
$cat_name = $ucs->cat;
}*/
printf('"children": [');
$rtitle = "SELECT title FROM table WHERE genre='$category'";
//Some other code of lesser relevance for this issue
$names = array();
while ($title2 = mysqli_fetch_object($ptitles)) {
$names[] = sprintf('"name": "%s"', $title2->title);
}
echo implode(',', $names);
printf(']');
printf('},');
//Some other code
Now the main issue is to have the comma out of the last print statement.
However, using implode for the category did not work out. In the previous topic a user pointed me out to add it before the code if it isn't the first output. However, would that work in this scenario? If so, how could I flag whether this is the first iteration?
I hope someone can help me out here,
Help is again very much appreciated,
Thanks in advance!

At the beginning of your loop set a variable to 0 and at the end of the loop increment it by 1. Then, use an if statement to see if the variable is equal to 0.
Use json_encode(), though. It will lead to cleaner, more maintainable code.

Related

JSON object with array header

this question comes from the posting I found here:
DataTables Multiple Tables from Multiple JSON Arrays
I'd like to know the simplest and best way to generate the JSON below. I can see the pattern is 'JSON object -> Array Header -> Array -> JSON object' but I do not know how to do this in PHP, from a mySQLi query result. I imagine having a mySQL table with a 'policies' and 'services' column so the query might look something like:
Select name, id, score, type from myTable where type = 'policies' and
type = 'services'
And the result would come back something like:
name id score type
A 1 0 policies
B 2 0 services
But then how would I take that query and generate this JSON in php?
{
"Policies": [
{
"name": "A",
"id": "1",
"score": "0"
}
],
"Services": [
{
"name": "B",
"id": "2",
"score": "0"
}
]
}
Thanks for your help!
Start by creating the new empty array.
Then, iterate through the result and add it in the correct sub-array:
$new = [];
foreach ($result as $item) {
// Uppercase the first character
$type = ucfirst($item['type']);
if (!isset($new[$type])) {
// This type doesn't exist in the new array yet, let's create it.
$new[$type] = [];
}
// Add the item
$new[$type][] = $item;
}
// Output it as json
echo json_encode($new, JSON_PRETTY_PRINT);
The above code will also work if new types are added to the database.
PS. The JSON_PRETTY_PRINT argument is just to make the json string a bit more readable while developing. When everything looks good, you can remove it.

PHP and JSON - extra comma in results

I'm trying to return json response in the correct format but I am getting an extra 'comma' in the returned code (comma after the last item 'Pencil'):
{
"results": [{
"ItemID": 1,
"ItemName": "Ball"
}, {
"ItemID": 2,
"ItemName": "Pen"
}, {
"ItemID": 3,
"ItemName": "Pencil"
},
}]
}
I tried different things but I can't get rid of it. Would anybody have any idea how to remove it?
The code that i have is this:
<?php
print '{"results":[';
for ($i=0; $i <$numrows; $i++) {
$stmt->fetch();
$JSONArray = array(
"ItemID" => $ItemID,
"ItemName" => $ItemName
);
print ",";
print json_encode($JSONArray);
}
print "]}"
?>
You're doing it ENTIRELY wrong. You're outputting multiple independent JSON strings, which is outright wrong. JSON is a monolithic "structure", and building it piece-wise is highly risky.
Simple: DOn't do that.
You build a standard PHP array, then do ONE SINGLE encoding when you're completely done building:
$arr = array();
for(...) {
$arr[] = ... add stuff ..
}
echo json_encode($arr);
First, fetching into bound variables is causing you an extra step, second, you don't need to construct any JSON. Just get all of your rows into the proper array structure and encode:
$result = $stmt->get_result();
while($rows['results'][] = $result->fetch_array(MYSQLI_ASSOC)){}
echo json_encode($rows);
If your system supports it, just use this instead of the while loop:
$rows['results'] = $result->fetch_all(MYSQLI_ASSOC);

Why can I not access the second level of this array in PHP?

Recently, with help from the Stack Oveflow community, I learned how to work with JSON data that I got from the Google API. So, I thought I had a grasp on how to do roughly the same kind of action with JSON data from Blogger, again using the Google API.
However, it's been driving me crazy. I can't seem to get a handle on how to get at the right level of the array that I need.
What I am trying to do is get a selection of blog posts and then cherry pick out information and display it. Should be straight forward.
Right now my blog has only three test entries. I want to see if I can loop through the array I create from the JSON to display data. If I use this code:
$recentBlog = json_decode(file_get_contents("https://www.googleapis.com/blogger/v3/blogs/xxxxxxxxxxxxxxxxxxxx/posts?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true));
foreach ($recentBlog as $item)
{
var_dump($item[0]);
}
... then I get data the first item only from the array. This makes sense to me. I looped through the array, but on each call, I only asked for the first item at the 0 position.
So I thought I would do this:
$recentBlog = json_decode(file_get_contents("https://www.googleapis.com/blogger/v3/blogs/xxxxxxxxxxxxxxxxxxxx/posts?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true));
$count = 0;
foreach ($recentBlog as $item)
{
var_dump($item[$count]);
$count = $count + 1;
}
... but I get the second and third item only. I do not get the first item anymore.
What is wrong with my code?
If it helps, this is Google's documentation about the format of the JSON that I get back.
You probably have a wrong parenthesis in your JSON decoding call:
$recentBlog = json_decode(file_get_contents("https://[...]"), true);
Note that I moved one parenthesis directly behind the file_get_contents() function. This way json_decode() will return you an iterable array.
You get the response like below. If you want to loop the blog entries you have to loop $recentBlog['items'] in foreach.
foreach ($recentBlog['items'] as $item)
{
var_dump($item);
}
Response:
{
"kind": "blogger#postList",
"nextPageToken": "CgkIChiAkceVjiYQ0b2SAQ",
"prevPageToken": "CgkIChDBwrK3mCYQ0b2SAQ",
"items": [
{
"kind": "blogger#post",
"id": "7706273476706534553",
"blog": {
"id": "2399953"
},
"published": "2011-08-01T19:58:00.000Z",
"updated": "2011-08-01T19:58:51.947Z",
"url": "http://buzz.blogger.com/2011/08/latest-updates-august-1st.html",
"selfLink": "https://www.googleapis.com/blogger/v3/blogs/2399953/posts/7706273476706534553",
"title": "Latest updates, August 1st",
"content": "elided for readability",
"author": {
"id": "401465483996",
"displayName": "Brett Wiltshire",
"url": "http://www.blogger.com/profile/01430672582309320414",
"image": {
"url": "http://4.bp.blogspot.com/_YA50adQ-7vQ/S1gfR_6ufpI/AAAAAAAAAAk/1ErJGgRWZDg/S45/brett.png"
}
},
"replies": {
"totalItems": "0",
"selfLink": "https://www.googleapis.com/blogger/v3/blogs/2399953/posts/7706273476706534553/comments"
}
},
{
"kind": "blogger#post",
"id": "6069922188027612413",
elided for readability
}
]
}

Pull specific value from JSON with PHP

I'm trying to pull the price from the following JSON but can't seem to figure out how to reference the actual values:
{"cards": [ { "high": "0.73", "volume": 1, "percent_change": "-2.67", "name": "Lightning Bolt", "url": "http://blacklotusproject.com/cards/Revised+Edition/Lightning+Bolt/", "price": "0.73", "set_code": "3ED", "average": "0.73", "change": "-0.02", "low": "0.73"}], "currency": "USD" }
So far I've got this code, which gets into the cards array but I'm unsure how to get farther - every attempt I've tried returns null.
$json = file_get_contents($url); $data = json_decode($json, TRUE);
echo var_dump($data[cards]);
Can someone shed light on what I need to do?
$data['cards'] has another array within it. You will need to access this array with index 0. For instance, $data['cards'][0]['high'] and so on.
$data['cards'] is an array itself, so you could do:
foreach ($data['cards'] AS $carditem) {
echo $carditem['high'];
...
}
to get all items in that array,
or if you only want the first item $data['cards'][0]['...']
To access using a string literal array index, always use quotes.
$data["cards"]
Link: PHP Documentation for Arrays

Proper way to push values to an array PHP?

I have run into a problem that is a little irritating. Here is my PHP code. Ignore where the variables are coming from. This is for shopping-cart functionality but it is applicable in many different areas.
$data_set = json_decode(stripslashes($_POST['varA']), true);
$pid = $pid['product_id'];
$quantity = $pid['quantity'];
$_SESSION['cartid'] = $_SESSION['cartid'] + 1;
$product_data = array("Product_ID" = > $pid, "quantity" = > $quantity, "cartid" = > $_SESSION['cartid']);
My issue is occurring at this place in the code. I first check to see if the Session variable has a value in it, if not then it proceeds to create an associative array.
if (empty($_SESSION['cart_items'])) {
$_SESSION['cart_items'] = array("items" = > $product_data);
} else {
array_push($_SESSION['cart_items']['items'], $product_data);
}
echo json_encode($_SESSION['cart_items']);
The end result after the first item is "added" looks like this:
{
"items": {
"Product_ID": "2",
"quantity": "1",
"cartid": 1
}
}
However, after several the first add, every value gets a key:
{
"items": {
"0": {
"Product_ID": "2",
"quantity": "1",
"cartid": 2
},
"1": {
"Product_ID": "2",
"quantity": "1",
"cartid": 3
},
"Product_ID": "2",
"quantity": "1",
"cartid": 1
}
}
How do I prevent these keys from occuring? Is this possible? If not, how can this be re-written so that the keys are added every time? And is this possible to parse and loop through in JS on the front end?
Sorry I have so many questions. Any help is really appreciated.
In the first iteration, the $_SESSION['cart_items'] is empty, so you run this:
$_SESSION['cart_items'] = array("items" => $product_data);
This creates $_SESSION['cart_items']['items'] but you populate it with just the product by itself; you should define it as an array instead:
$_SESSION['cart_items'] = array("items" => array($product_data));
This creates an array with a single item which you can later extend with array_push.
Having said that, you can replace the whole condition with just:
$_SESSION['cart_items']['items'][] = $product_date;
PHP will automatically create an empty array if it didn't exist yet, followed by adding the product data as the next element.
This is because of this line:
$_SESSION['cart_items'] = array("items" = > $product_data);
You essentially say in that line that 'items' key has product data, instead of key in items. It should be:
$_SESSION['cart_items']['items'] = array($product_data);
Keys -will- always occur, unless you want data to overwrite another. If you do not want keys (0,1 etc) then the only other option is merging data. In which case it would be:
$_SESSION['cart_items']['items']+=$product_data;
..but I don't think that is what you want.
You don't need the items, try the below way.
if (empty($_SESSION['cart_items'])) {
$_SESSION['cart_items'] = array($product_data);
} else {
$_SESSION['cart_items'][] = $product_data;
}

Categories