Pull nested JSON data using foreach loop in php - php

I want to pull data from below JSON format using PHP (foreach loop).
User detail is correspondence to house detail and house detail correspondence to individual meter reading.
I want to show Username, Device_No and all meter_detail field. Please help me out.
{
"id": 7,
"Username": "user",
"Housename": "Leela",
"Houses_list": [{
"id": 1,
"Device_No": 1111,
"meter_detail": [{
"id": 1,
"flow": 12,
"date": "2020-02-13T12:05:14.709Z",
"opening": 5,
"volume": 1234
},
{
"id": 2,
"flow": 32,
"date": "2020-02-13T12:05:26.821Z",
"opening": 2,
"volume": 1235
}
]
},
{
"id": 2,
"Device_No": 231,
"meter_detail": [{
"id": 3,
"flow": 78,
"date": "2020-02-13T12:05:41.331Z",
"opening": 5,
"volume": 7854
}]
}
]
}

You need to convert the JSON to an array by using json_decode(). Then a couple of foreach loops would do work for you:
<?php
$json = '{
"id": 7,
"Username": "user",
"Housename": "Leela",
"Houses_list": [{
"id": 1,
"Device_No": 1111,
"meter_detail": [{
"id": 1,
"flow": 12,
"date": "2020-02-13T12:05:14.709Z",
"opening": 5,
"volume": 1234
},
{
"id": 2,
"flow": 32,
"date": "2020-02-13T12:05:26.821Z",
"opening": 2,
"volume": 1235
}
]
},
{
"id": 2,
"Device_No": 231,
"meter_detail": [{
"id": 3,
"flow": 78,
"date": "2020-02-13T12:05:41.331Z",
"opening": 5,
"volume": 7854
}]
}
]
}';
$input = json_decode($json, true);
echo 'Username: '.$input['Username'].'<br>';
foreach ($input['Houses_list'] as $device){
echo '<br>Device No: '.$device['Device_No'].'<br>';
foreach ($device['meter_detail'] as $metrics){
echo '<table style="border: 1px solid black">';
foreach ($metrics as $key => $metric){
echo '<tr><td>'.$key.'</td><td>'.$metric.'</td></tr>';
}
echo '</table>';
}
}
?>
Output:

Related

Need to find maximum level where child is present in a parent child relationship

Here is the JSON object, so if I look at below object it has children till level 3 and object at level 3 has no children's.
So what is the efficient way to find out?
{
"id": 2,
"name": "Economic Segment",
"maxLevel": 10,
"parentId": null,
"children": [
{
"id": 7,
"name": "Revenue",
"maxLevel": 9,
"parentId": 2,
"children": [
{
"id": 12,
"name": "R Child",
"maxLevel": 8,
"parentId": 7,
"children": [
{
"id": 12,
"name": "R Child",
"maxLevel": 8,
"parentId": 7,
"children": []
}
]
}
]
},
{
"id": 8,
"name": "Expenditure",
"maxLevel": 9,
"parentId": 2,
"children": []
},
{
"id": 9,
"name": "Asset",
"maxLevel": 9,
"parentId": 2,
"children": []
}
]
}}

Retrieve elements from data table and sum the same elements

I have the table "orders" from woocommerce.
I filtered and get sorted the elements by status with GET request.
The results are copied to a JSON file.
So now, I want to find the elements with the same "product_id" and their values and summarize them to display in screen so I can print them.
For example:
"product_id": 45329,
"variation_id": 0,
"quantity": 1
"product_id": 48911,
"variation_id": 0,
"quantity": 1,
"product_id": 45329,
"variation_id": 0,
"quantity": 1
The output that I want to achieve is this:
45329 quantity 2
48911 quantity 1
Thanks!
Decode JSON with json_decode() and make calculations. Next example uses simplified JSON data, which I think matches the format from WooCommerce (I guess this format is from list orders GET request):
<?php
# JSON
$json = '
[
{
"id": 727,
"line_items": [
{
"id": 315,
"name": "Woo Single #1",
"product_id": 93,
"variation_id": 0,
"quantity": 2,
"tax_class": "",
"subtotal": "6.00",
"subtotal_tax": "0.45",
"total": "6.00",
"total_tax": "0.45",
"taxes": [
{
"id": 75,
"total": "0.45",
"subtotal": "0.45"
}
],
"meta_data": [],
"sku": "",
"price": 3
},
{
"id": 316,
"name": "Ship Your Idea – Color: Black, Size: M Test",
"product_id": 22,
"variation_id": 23,
"quantity": 1,
"tax_class": "",
"subtotal": "12.00",
"subtotal_tax": "0.90",
"total": "12.00",
"total_tax": "0.90",
"taxes": [
{
"id": 75,
"total": "0.9",
"subtotal": "0.9"
}
],
"meta_data": [
{
"id": 2095,
"key": "pa_color",
"value": "black"
},
{
"id": 2096,
"key": "size",
"value": "M Test"
}
],
"sku": "Bar3",
"price": 12
}
]
}
]';
$input = json_decode($json, true);
# Sum
$output = array();
foreach ($input as $order) {
foreach ($order["line_items"] as $item) {
$product_id = $item['product_id'];
$quantity = $item['quantity'];
if (!array_key_exists($product_id, $output)) {
$output[$product_id] = 0;
}
$output[$product_id] += $quantity;
}
}
#Output
foreach ($output as $key => $value) {
echo $key.' quantity '.$value.'<br>';
}
?>
Output:
93 quantity 2
22 quantity 1

Laravel 5.3 - Merge array based on 2 matching keys?

Given the following two arrays, how can they be merged efficiently to result in the third array?
productData
$productData =
[
{
"product_id": 4,
"type": "electronic",
"name": "monitor",
"specs": {
"HDMI": true,
"VGA": false
}
},
{
"product_id": 5,
"type": "electronic",
"name": "HDMI cable",
"specs": {
"length": "3ft"
}
},
{
"product_id": 6,
"type": "kitchen",
"name": "spoon"
}
]
products
$products =
{
"products": 3,
"per_page": 10,
"current_page": 1,
"data": [
{
"id": 4,
"product_type": "electronic",
"product_id": 6
},
{
"id": 6,
"type": "electronic",
"product_id": 5
},
{
"id": 9,
"type": "kitchen",
"product_id": 4
}
]
}
productsFinal ($productData merged into $products - based on matching combo of product_id/product_id and type/product_type)
$productsFinal =
{
"products": 3,
"per_page": 10,
"current_page": 1,
"data": [
{
"id": 4,
"product_type": "electronic",
"product_id": 6,
// How to merge product data and wrap with "data" key
"data": {
"product_id": 6,
"type": "kitchen",
"name": "spoon"
}
},
{
"id": 6,
"type": "electronic",
"product_id": 5,
// How to merge product data and wrap in "data" key
"data": {
"product_id": 5,
"type": "electronic",
"name": "HDMI cable",
"specs": {
"length": "3ft"
}
}
},
{
"id": 9,
"type": "kitchen",
"product_id": 4,
// How to merge product data and wrap in "data" key
"data": {
"product_id": 6,
"type": "kitchen",
"name": "spoon"
}
}
]
}
I tried different things for the outcome in a foreach loop but still cannot get it to render as intended:
foreach($productData as $productDataItem) {
// when $productDataItem.product_id == $product.product_id && $productDataItem.type == $product.product_type
// move the matching $productDataItem object into matching $product object, wrapped in a new "data" key
}
I don't know Laravel too well. However you can join your data objects quite easily:
<?php
$productData = json_decode('[
{
"product_id": 4,
"type": "electronic",
"name": "monitor",
"specs": {
"HDMI": true,
"VGA": false
}
},
{
"product_id": 5,
"type": "electronic",
"name": "HDMI cable",
"specs": {
"length": "3ft"
}
},
{
"product_id": 6,
"type": "kitchen",
"name": "spoon"
}
]');
$products = json_decode('{
"products": 3,
"per_page": 10,
"current_page": 1,
"data": [
{
"id": 4,
"type": "electronic",
"product_id": 6
},
{
"id": 6,
"type": "electronic",
"product_id": 5
},
{
"id": 9,
"type": "kitchen",
"product_id": 4
}
]
}');
// combine both data objects
foreach($products->data As &$p) {
foreach($productData As $d) {
if(property_exists($p, "product_id") && property_exists($d, "product_id") && property_exists($p, "type") && property_exists($d, "type")) {
if($p->product_id==$d->product_id && $p->type==$d->type) {
//$p = (object) array_merge((array) $p, (array) $d);
$p->data = $d; // updated answer
continue;
}
}
}
}
echo("<pre>");
echo json_encode($products, JSON_PRETTY_PRINT);
?>
You can test the code here: http://sandbox.onlinephpfunctions.com/code/98a50c35ee32c30f0d2be1661f7afb5895174cbe
Update: http://sandbox.onlinephpfunctions.com/code/aeebfdcf4f4db5e960260e931982570cfed19e0e
I would suggest to check this package dingo/api. I assume you want to display some kind of JSON response. Take a look at Transformers. You can do something like this :
<?php
namespace App\Http\Transformers;
use App\Http\Controllers\ProductData;
use League\Fractal\TransformerAbstract;
class ProductsDataTransformer extends TransformerAbstract
{
/**
* Turn this item object into a generic array
*
* #return array
*/
public function transform(ProductData $productdata)
{
return [
'id' => $productdata->id,
'product_type' => $productdata->product_type,
'product /*or data*/' => Product::find($productdata->product_id),
];
}
}
This would find the product by it's ID and look like this :
{
"id": 4,
"product_type": "electronic",
"product" {
"product_id": 6,
"type": "kitchen",
"name": "spoon"
},
},
You can then also create a transformer for Product to take care of your specs attribute to do the same thing.

Getting data out of a JSON API with PHP

Im having trouble extracting data from a API, i would like to use for a school project..
The link to the API i here
Or here's a sample of the API output
{
"help": "http://www.odaa.dk/api/3/action/help_show?name=datastore_search",
"success": true,
"result": {
"resource_id": "2a82a145-0195-4081-a13c-b0e587e9b89c",
"fields": [
{
"type": "int4",
"id": "_id"
},
{
"type": "text",
"id": "date"
},
{
"type": "text",
"id": "garageCode"
},
{
"type": "int4",
"id": "totalSpaces"
},
{
"type": "int4",
"id": "vehicleCount"
}
],
"records": [
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 62,
"_id": 1,
"totalSpaces": 65,
"garageCode": "NORREPORT"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 512,
"_id": 2,
"totalSpaces": 512,
"garageCode": "SKOLEBAKKEN"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 236,
"_id": 3,
"totalSpaces": 1240,
"garageCode": "SCANDCENTER"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 40,
"_id": 4,
"totalSpaces": 953,
"garageCode": "BRUUNS"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 2932,
"_id": 5,
"totalSpaces": 142,
"garageCode": "BUSGADEHUSET"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 18,
"_id": 6,
"totalSpaces": 383,
"garageCode": "MAGASIN"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 3,
"_id": 7,
"totalSpaces": 210,
"garageCode": "KALKVAERKSVEJ"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 255,
"_id": 8,
"totalSpaces": 700,
"garageCode": "SALLING"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 0,
"_id": 9,
"totalSpaces": 0,
"garageCode": "DOKK1"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 34,
"_id": 10,
"totalSpaces": 449,
"garageCode": "Navitas"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 105,
"_id": 11,
"totalSpaces": 105,
"garageCode": "NewBusgadehuset"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 9,
"_id": 12,
"totalSpaces": 319,
"garageCode": "Urban Level 1"
},
{
"date": "2015/11/11 03:50:07",
"vehicleCount": 15,
"_id": 13,
"totalSpaces": 654,
"garageCode": "Urban Level 2+3"
}
],
"_links": {
"start": "/api/action/datastore_search?resource_id=2a82a145-0195-4081-a13c-b0e587e9b89c",
"next": "/api/action/datastore_search?offset=100&resource_id=2a82a145-0195-4081-a13c-b0e587e9b89c"
},
"total": 13
}
}
I would like to extract the cells called "vehicleCount" and "_id", but i seems I can't figure out how to do it :(
$json = file_get_contents('http://www.odaa.dk/api/action/datastore_search?resource_id=2a82a145-0195-4081-a13c-b0e587e9b89c');
$json = json_decode($json);
echo $json->fields->_id;
I have tried many different ways, but now loss of ideas and its 4 o'clock in the morning, so hopefully someone can help me.
if you want to extract the cells vehicleCount and _id
This is my solution for you:
<?php
$json = file_get_contents('http://www.odaa.dk/api/action/datastore_search?resource_id=2a82a145-0195-4081-a13c-b0e587e9b89c');
$json = json_decode($json);
foreach ($json->result->records as $val) {
echo "_id = " .$val->_id . " vehicleCount = " . $val->vehicleCount . "<br>";
}
?>
$json->result->records[0]->_id

Getting unique results with elasticsearch acorrding to field

I'm using FOSElasticaBundle with Symfony2 on my project and there are entry and user tables on MySQL database and each entry belongs to one user.
I want to get just one entry per a user among the whole entries from the database.
Entries Representation
[
{
"id": 1,
"name": "Hello world",
"user": {
"id": 17,
"username": "foo"
}
},
{
"id": 2,
"name": "Lorem ipsum",
"user": {
"id": 15,
"username": "bar"
}
},
{
"id": 3,
"name": "Dolar sit amet",
"user": {
"id": 17,
"username": "foo"
}
},
]
Expected result is:
[
{
"id": 1,
"name": "Hello world",
"user": {
"id": 17,
"username": "foo"
}
},
{
"id": 2,
"name": "Lorem ipsum",
"user": {
"id": 15,
"username": "bar"
}
}
]
But it returns all entries on table. I've tried to add an aggregation to my elasticsearch query and nothing changed.
$distinctAgg = new \Elastica\Aggregation\Terms("distinctAgg");
$distinctAgg->setField("user.id");
$distinctAgg->setSize(1);
$query->addAggregation($distinctAgg);
Is there any way to do this via term filter or anything else? Any help would be great. Thank you.
Aggregations are not easy to understand when you are used to MySQL group by.
The first thing, is that aggregations results are not returned in hits, but in aggregations. So when you get the result of your search, you have to get aggregations like that :
$results = $search->search();
$aggregationsResults = $results->getAggregations();
The second thing is that aggregations wont return you the source. With the aggregation of your example, you will only know that you have 1 user with ID 15, and 2 users with ID 15.
E.g. with this query :
{
"query": {
"match_all": {}
},
"aggs": {
"byUser": {
"terms": {
"field": "user.id"
}
}
}
}
Result:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [ ... ]
},
"aggregations": {
"byUser": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 17,
"doc_count": 2
},
{
"key": 15,
"doc_count": 1
}
]
}
}
}
If you want to get results, the same way you would do with a GROUP BY in MySQL, you have to use a top_hits sub-aggregation:
{
"query": {
"match_all": {}
},
"aggs": {
"byUser": {
"terms": {
"field": "user.id"
},
"aggs": {
"results": {
"top_hits": {
"size": 1
}
}
}
}
}
}
Result:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [ ... ]
},
"aggregations": {
"byUser": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 17,
"doc_count": 2,
"results": {
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test_stackoverflow",
"_type": "test1",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"name": "Hello world",
"user": {
"id": 17,
"username": "foo"
}
}
}
]
}
}
},
{
"key": 15,
"doc_count": 1,
"results": {
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test_stackoverflow",
"_type": "test1",
"_id": "2",
"_score": 1,
"_source": {
"id": 2,
"name": "Lorem ipsum",
"user": {
"id": 15,
"username": "bar"
}
}
}
]
}
}
}
]
}
}
}
More informations on this page : https://www.elastic.co/blog/top-hits-aggregation

Categories