Loop in nested json array PHP - php

Sample of json string that receive by post is here:
[
{
"gc": [
{
"id": "1",
"ti": "title1",
"oid": 1,
"mid": "1-2",
"mc": 2,
"gct": 1,
"ma": 1,
"isu": 0
}
],
"gcm": [
{
"mid": "11",
"gcid":"1",
"sid": 58,
"msg": "msg1 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
},
{
"mid": "12",
"gcid":"1",
"sid": 58,
"msg": "msg2 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
}
],
"gcms": [
{
"id": "111",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "112",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "121",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
},
{
"id": "122",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
}
]
}
]
I use below code to loop in decoded array but only loop 1 time in array:
$json = json_decode($input, true);
foreach ($json as $value) {
$this->logger->info("Start update_new_data ->");
if (isset($value['gc'])) {
$this->logger->info("gc key exist");
foreach ($value["gc"] as $jObj) {
}
} else {
if (isset($value['gcm'])) {
$this->logger->info("gcm key exist");
foreach ($value["gcm"] as $jObj) {
}
} else {
if (isset($value['gcms'])) {
$this->logger->info("gcms key exist");
foreach ($value["gcms"] as $jObj) {
}
}
}
}
$this->logger->info("End update_new_data ->");
}
I want loop in array, if key is 'gc' loop in 'gc' array and loop again and if key is 'gcm' loop in 'gcm' array and if key is 'gcms' loop in 'gcms' array. I have to check the key because key mybe not exist in json string.
Test many code but can't solve problem.
How can i do this?

#mohammadi This Can work for you.
$json = json_decode($input, true);
$json = isset($json[0])?$json[0]:'';
$this->logger->info("Start update_new_data ->");
if(!empty($json)){
foreach ($json as $Key=>$value) {
if(isset($Key)){
if ($Key == "gc") {
$this->logger->info("gc key exist");
foreach ($value as $jObj) {
}
}
else if ($Key == "gcm") {
$this->logger->info("gcm key exist");
foreach ($value as $jObj) {
}
}
else if ($Key == "gcms") {
$this->logger->info("gcms key exist");
foreach ($value as $jObj) {
}
}
}
$this->logger->info("End update_new_data ->");
}
}
you can use this "$json = isset($json[0])?$json[0]:'';"line if you do not want to change the json structure because of the whole json date(array) inside a single array so you can get the first index of the array. if you change the json like this (shown below) then you did not require this "$json = isset($json[0])?$json[0]:'';"
$input = '{
"gc": [
{
"id": "1",
"ti": "title1",
"oid": 1,
"mid": "1-2",
"mc": 2,
"gct": 1,
"ma": 1,
"isu": 0
}
],
"gcm": [
{
"mid": "11",
"gcid":"1",
"sid": 58,
"msg": "msg1 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
},
{
"mid": "12",
"gcid":"1",
"sid": 58,
"msg": "msg2 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
}
],
"gcms": [
{
"id": "111",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "112",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "121",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
},
{
"id": "122",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
}
]
}';

As per the json given in the question, the decoded array has single element which encloses all the elements. In that case, instead of looping through $json like: foreach ($json.., try looping through $json[0] like: foreach ($json[0]... And to get the key, you don't have to use array_keys, just run the loop with key like: foreach ($json[0] as $key => $value)...

I don't see any reason to use a loop for the outer array. Simply access the parts you want directly:
$json = json_decode($input, true);
$value = $json[0];
$this->logger->info("Start update_new_data ->");
if (isset($value['gc'])) {
$this->logger->info("gc key exist");
foreach ($value["gc"] as $jObj) {
}
}
if (isset($value['gcm'])) {
$this->logger->info("gcm key exist");
foreach ($value["gcm"] as $jObj) {
}
}
if (isset($value['gcms'])) {
$this->logger->info("gcms key exist");
foreach ($value["gcms"] as $jObj) {
}
}
$this->logger->info("End update_new_data ->");
This way you see your json structure more clearly (array inside an array).

Try to use array_keys for iteration:
$json = json_decode($input, true);
$json_keys = array_keys($json);
foreach ($json_keys as $json_key) {
$item = $json[$json_key];
foreach ($item as $row) {
foreach ($row as $subrow) {
echo isset($subrow['id']) ? $subrow['id'] : 'nope';
}
}
}

Related

How to prevent duplication of object inside by pushing it to the array in php?

I have question, is it possible not to duplicate the array object by looping on it? Right now I used laravel as my backend
I have here my response which is the exchange object duplicate itself.
[
{
"exchange": {
"id": 1,
"branch": "BB1",
"old_check_no": "0001",
"cash": "250000",
"bank_deposit": "1000000",
"offset": "250000",
"amount": "10000",
"over_under": null,
"checkDate": "2021-09-11",
"remarks": "1",
"date_closed": "2021-09-11"
},
"exchange_list": {
"exchange_id": 1,
"new_check_no": "001",
"new_check_bank": "bank",
"new_check_branch": "Lagros"
}
},
{
"exchange": {
"id": 1,
"branch": "BB1",
"old_check_no": "0001",
"cash": "250000",
"bank_deposit": "1000000",
"offset": "250000",
"amount": "10000",
"over_under": null,
"checkDate": "2021-09-11",
"remarks": "1",
"date_closed": "2021-09-11"
},
"exchange_list": {
"exchange_id": 1,
"new_check_no": "002",
"new_check_bank": "bank",
"new_check_branch": "Lagros"
}
},
]
Now my goal is to push the exchange without duplication:
[
{
"exchange": {
"id": 1,
"branch": "BB1",
"old_check_no": "0001",
"cash": "250000",
"bank_deposit": "1000000",
"offset": "250000",
"amount": "10000",
"over_under": null,
"checkDate": "2021-09-11",
"remarks": "1",
"date_closed": "2021-09-11"
},
"exchange_list": {
"exchange_id": 1,
"new_check_no": "001",
"new_check_bank": "bank",
"new_check_branch": "Lagros"
},
"exchange_list": {
"exchange_id": 1,
"new_check_no": "002",
"new_check_bank": "bank",
"new_check_branch": "Lagros"
}
}
]
Here is what my foreach loop like and how i push the array object.
$myArray = [];
foreach($exchange_check as $primary_array) {
foreach($exchange_lists as $second_array) {
if($second_array->exchange_id == $primary_array->id) {
array_push($myArray, (object)[
'exchange' => $primary_array,
'exchange_list' => $second_array,
]);
}
}
}
Thanks
You should add exchange data to array only once in first loop:
$myArray = [];
foreach($exchange_check as $primary_array) {
$idx = array_push($myArray, ['exchange' => $primary_array]);
foreach($exchange_lists as $second_array) {
if($second_array->exchange_id == $primary_array->id) {
//array_push() returns the new number of elements in the array,
//to get currently added array element we should subtract 1 from this number
$myArray[$idx-1]['exchange_list'][] = $second_array;
}
}
}
And in second loop add only exchange_list data to array.

php foreach nested loop retrieve all records

$json_string = '{
"response_code": 200,
"info": {
"days": [
{
"code": "A",
"runs": "111"
},
{
"code": "B",
"runs": "222"
},
{
"code": "C",
"runs": "333"
}
],
"name": "SUPER MARIO",
"number": "010203",
"classes": [
{
"points": "6523",
"name": "ABC",
"available": "N"
},
{
"points": "4253",
"name": "XYZ",
"available": "N"
},
{
"points": "2323",
"name": "JOHN",
"available": "N"
},
{
"points": "5236",
"name": "TAMIL",
"available": "N"
}
]
}
}';
$jsondata = $json_string;
$arr = json_decode($jsondata, true);
foreach($arr as $k=>$v)
{
echo $k."<br>";
}
it prints
response_code
info
But, I need the results like this
6523 ABC
4253 XYZ
2323 JOHN
5326 TAMIL
I have tried and achieved this above results using this below code. But, I want to do it using foreach loop. How do list out all information using foreach?
echo "".$arr['info']['classes'][0]['points']." ".$arr['info']['classes'][0]['name']."<br/>";
echo "".$arr['info']['classes'][1]['points']." ".$arr['info']['classes'][1]['name']."<br/>";
echo "".$arr['info']['classes'][2]['points']." ".$arr['info']['classes'][2]['name']."<br/>";
echo "".$arr['info']['classes'][3]['points']." ".$arr['info']['classes'][3]['name']."<br/>";
You should foreach your array key
foreach($arr['info']['classes'] as $k=>$v)
{
echo $v['points']." " . $v['name']."<br>";
}

Laravel : How do I return parent > child relationship from same table

I have a 3 tables product, category, attributes. In attributes table there is parent_id used for sub-attributes in a same table.Using loop I get a data.
My code :
$productDetails = Product::with('categories')->get();
foreach ($productDetails as $key => $value) {
foreach ($value->categories as $key => $value) {
$attributes = Attribute::where('product_id',$value->product_id)->where('category_id',$value->id)->where('parent_id',Null)->get();
$value->Attributes = $attributes;
foreach ($attributes as $key => $value) {
$subAttributes = Attribute::where('parent_id', $value->id)->get();
$value->subAttributes = $subAttributes;
}
}
}
Output :
{
"productDetails": [
{
"id": 1,
"title": "Small Size Diamond",
"icon": null,
"status": "Active",
"categories": [
{
"id": 1,
"product_id": 1,
"title": "Sieve Size",
"status": "Active",
"sort_order": 1,
"Attributes": [
{
"id": 1,
"product_id": 1,
"category_id": 1,
"parent_id": null,
"title": "- 2.0",
"status": "Active",
"sort_order": 1,
"subAttributes": [
[
{
"id": 9,
"product_id": 1,
"category_id": 1,
"parent_id": 1, // Attributes table ID
"title": "+ 0000 - 000",
"status": "Active",
"sort_order": 1
},
{
"id": 10,
"product_id": 1,
"category_id": 1,
"parent_id": 1, // Attributes table ID
"title": "+ 000 - 00",
"status": "Active",
"sort_order": 2
}
]
]
}
]
}
]
}
]}
The problem is in first product I gt completed response but in other prodcts in loop I do not get subAttributes data. How can i do this?
Simple, please do not use same variable name in all foreach loop,
Your code should like following
$productDetails = Product::with('categories')->get();
foreach ($productDetails as $pro_key => $pro_value) {
foreach ($pro_value->categories as $cat_key => $cat_value) {
$attributes = Attribute::where('product_id',$cat_value->product_id)->where('category_id',$cat_value->id)->where('parent_id',Null)->get();
$cat_value->Attributes = $attributes;
foreach ($attributes as $att_key => $att_value) {
$subAttributes = Attribute::where('parent_id', $att_value->id)->get();
$att_value->subAttributes = $subAttributes;
}
}
}

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
?>

Recursively sorting a JSON array

I've looked a little and found an answer that partially does what I am interested in doing, see: Sorting a JSON array in PHP
I have some decoded JSON that looks like this, just a sample.
{
"status": "OK",
"page": {
"rows": 5000,
"more": 0,
"number": 1
},
"accounts": [
{
"connected": 0,
"settings": {
"link_first_study_only": "0",
"update_study_source_on_notify": "1",
"link_external_whitelist": "",
"other_ingress_tags": ""
},
"must_approve_upload": 0,
"css": null,
"share_via_gateway": 0,
"password_expire": 90,
"vanity": "medpics"
}
]
}
What I would like to do is sort everything alphabetically so that it is easier to read and uniform. So that what I would see is:
{
"accounts": [
{
"css": null,
"connected": 0,
"must_approve_upload": 0,
"password_expire": 90,
"settings": {
"link_external_whitelist": "",
"link_first_study_only": "0",
"other_ingress_tags": "",
"update_study_source_on_notify": "1"
},
"share_via_gateway": 0,
"vanity": "medpics"
}
],
"page": {
"more": 0,
"number": 1,
"rows": 5000,
}
"status": "OK"
}
Every element is sorted alphabetically. Is that possible ?
Pretty straightforward
$json = <<<JSON
{
"status": "OK",
"page": {
"rows": 5000,
"more": 0,
"number": 1
},
"accounts": [
{
"connected": 0,
"settings": {
"link_first_study_only": "0",
"update_study_source_on_notify": "1",
"link_external_whitelist": "",
"other_ingress_tags": ""
},
"must_approve_upload": 0,
"css": null,
"share_via_gateway": 0,
"password_expire": 90,
"vanity": "medpics"
}
]
}
JSON;
$json = json_decode($json, true);
function ksort_recursive(&$array) {
ksort($array);
foreach ($array as &$value) {
if (is_array($value)) {
ksort_recursive($value);
}
}
}
ksort_recursive($json);
print_r($json);
Proof of solution here
https://3v4l.org/qUAA0

Categories