PHP Assotiative array -> recursive traverse not working - php

I have an associative array object :
[ {
"id": 15,
"owner_id": 1,
"container_info": {
"id": 1,
"container_id": 15
},
"filters": [
{
"id": 3,
"parent_id": null
},
{
"id": 6,
"parent_id": null
}
],
"children_recursive": [
{
"id": 7,
"owner_id": 1,
"container_info": null,
"filters": [
],
"children_recursive": [
{
"id": 8,
"owner_id": 1,
"container_info": null,
"filters": [
],
"children_recursive": [
]
}
]
},
{
"id": 16,
"owner_id": 1,
"container_info": {
"id": 2,
"container_id": 16
},
"filters": [
],
"children_recursive": [
]
},
]
}
]
I want to recursively loop through all object and their children_recursive key. And each children_recursive object (at any depth) needs to be processed
So I used :
public function traverseContainerRecursively($containerItems)
{
Log:info(' CHECK 1');
foreach ($containerItems as $containerItem) {
Log::info(json_encode($containerItem->id));
Log::info(json_encode($containerItem->owner_id));
Log::info(json_encode($containerItem->container_info));
Log::info(json_encode($containerItem->children_recursive));
}
Log::info(' CHECK 2');
foreach ($containerItems as $containerItem) {
Log::info(json_encode($containerItem['id']));
Log::info(json_encode($containerItem['owner_id']));
Log::info(json_encode($containerItem['container_info']));
Log::info(json_encode($containerItem['children_recursive']));
}
Log::info(' CHECK 3');
foreach ($containerItems as $key=>$value) {
if( $key == "children_recursive" ) {
Log::info(json_encode($value));
$this->traverseContainerRecursively($value);
}
} //foreach end
}
OUTPUT :
CHECK 1
15
1
null
null
CHECK 2
15
1
null
null
CHECK 3
{
"id": 15,
"owner_id": 1,
"container_info": {
"id": 1,
"container_id": 15
},
"filters": [
{
"id": 3,
"parent_id": null
},
{
"id": 6,
"parent_id": null
}
],
"children_recursive": [
{
"id": 7,
"owner_id": 1,
"container_info": null,
"filters": [
],
"children_recursive": [
{
"id": 8,
"owner_id": 1,
"container_info": null,
"filters": [
],
"children_recursive": [
]
}
]
},
{
"id": 16,
"owner_id": 1,
"container_info": {
"id": 2,
"container_id": 16
},
"filters": [
],
"children_recursive": [
]
},
]
} // i.e. the entire passed object
So I am unable to retrieve the value for key "children_recursive".
Please guide.

I figured out the issue.
Following code worked:
$obj = json_decode($containerItem);
Log::info(json_encode($obj->children_recursive));

Related

How to modify nested Laravel collection using group by

I want to modify nested collection using group by.
This is sample collection
"document": [
{
"id": 1,
"company_id": 4,
"client_id": 1,
"status": 1,
"client": {
"id": 1,
"company_id": 4,
"name": "1663159185735-client"
},
"document_items": [
{
"id": 1,
"master_id": 5,
"text_value": "piyo",
},
{
"id": 2,
"master_id": 5,
"text_value": "fuga",
},
{
"id": 3,
"master_id": 3,
"text_value": "hoge",
}
]
}
]
I want to change like this.
"document": [
{
"id": 1,
"company_id": 4,
"client_id": 1,
"status": 1,
"client": {
"id": 1,
"company_id": 4,
"name": "1663159185735-client"
},
"document_items": [
5: [{
"id": 1,
"master_id": 5,
"text_value": "piyo",
},
{
"id": 2,
"master_id": 5,
"text_value": "fuga",
}
],
3: [{
"id": 2,
"master_id": 5,
"text_value": "fuga",
       }
     ]
]
}
]
I try write below code;
$result->map(function ($v){
$v->documentItems = $v->documentItems->groupBy('master_id');
return $v;
});
but output key is documentItems not document_items
I changed to
$v->document_items = $v->documentItems->groupBy('master_id');
key is drawing_drawing_items but not groupby(simple array)
how to modify group by and preserve key case?
I changed to
$v->document_items = $v->documentItems->groupBy('master_id');
key is drawing_drawing_items but not groupby(simple array)
You should also change like this $v->document_items->groupBy('master_id')
The key is 'document_items' not 'documentItems'

Group by an item in a nested array using laravel collection

I have an array that has the variable name $array and it is as follows:
$array = [
"data"=> [
[
"company"=>[
"id"=> 1,
"name"=> "company1"
],
"reports"=> [
"active_reports"=> 3,
"completed_reports"=> 2
]
],
[
"company"=>[
"id"=> 2,
"name"=> "company2"
],
"reports"=> [
"active_reports"=> 6,
"completed_reports"=> 1
]
],
[
"company"=>[
"id"=> 2,
"name"=> "company2"
],
"reports"=> [
"active_reports"=> 7,
"completed_reports"=> 5
]
]
]
];
So, I want to group this array by the company id. The id can be found in the nested array with key company
My expected result is below:
{
"1": [
{
"company": {
"id": 1,
"name": "company1"
},
"reports": {
"active_reports": 3,
"completed_reports": 2
}
}
],
"2": [
{
"company": {
"id": 2,
"name": "company2"
},
"reports": {
"active_reports": 6,
"completed_reports": 1
}
},
{
"company": {
"id": 2,
"name": "company2"
},
"reports": {
"active_reports": 7,
"completed_reports": 5
}
}
]
}
So, I tried the following logic:
foreach ($array['data'] as $data) {
$reportsData = collect($data)->groupBy($data['company']['id']);
Log::info($reportsData);
}
But this is the result I'm getting after trying the above logic:
[
{
"": [
{
"id": 1,
"name": "company1"
},
{
"active_reports": 3,
"completed_reports": 2
}
]
},
{
"": [
{
"id": 2,
"name": "company2"
},
{
"active_reports": 6,
"completed_reports": 1
}
]
},
{
"": [
{
"id": 2,
"name": "company2"
},
{
"active_reports": 7,
"completed_reports": 5
}
]
}
]
I want to be able to get the expected result as illustrated above.
You are passing a value to groupBy currently not a 'column' to group by. Though you have nested data here so you will need to pass a callback to groupBy where you will return what value the entities should be grouped by:
collect($array['data'])
->groupBy(fn ($item) => $item['company']['id']);
Or simply using the 'dot' notation (as mentioned by Donkarnash), since we are starting the collection at the 'data' key:
collect($array['data'])->groupBy('company.id');
Laravel 9.x Docs - Collections - Available Methods - groupBy

Loop through every occurrence of specific child key in a nested structure

I have this payload,
[
{
"id": 1,
"name": "T-Shirt",
"children_rec": [
{
"id": 2,
"name": "Classic",
"children_rec": [
{
"id": 3,
"name": "Lycra",
"children_rec": []
}
]
},
{
"id": 4,
"name": "Plain",
"children_rec": []
}
]
},
{
"id": 5,
"name": "Shirt",
"children_rec": [
{
"id": 6,
"name": "Plain",
"children_rec": []
}
]
}
]
I want to loop through every occurrence of children_rec.
What I have tried is,
foreach ($mainCategories as $category) {
if (!empty($category['children_rec'])) {
foreach ($category['children_rec'] as $child) {
if (!empty($category['children_rec'])) {
var_dump($child);
}
}
}
}
But this is not the dynamic way to achieve this. What if I have 5 or 6 level of childer_rec. How can I achieve this?
Edit
#ggorlen's way is cool, but What if I need this output?
[
{
"id": 1,
"name": "T-Shirt",
"children": [
"2",
"3",
"4"
]
},
{
"id": 5,
"name": "Shirt",
"children": [
"6"
]
}
]
Since you don't know the depth, you'll need a stack or recursion. Here's a solution with a stack:
<?php
$tree = json_decode('[ { "id": 1, "name": "T-Shirt", "children_rec": [ { "id": 2, "name": "Classic", "children_rec": [ { "id": 3, "name": "Lycra", "children_rec": [] } ] }, { "id": 4, "name": "Plain", "children_rec": [] } ] }, { "id": 5, "name": "Shirt", "children_rec": [ { "id": 6, "name": "Plain", "children_rec": [] } ] } ]', true);
for ($stack = $tree; !empty($stack);) {
$curr = array_pop($stack);
$flattened[] = $curr["name"]; // or just $curr if you only want the node
if (!empty($curr["children_rec"])) {
array_push($stack, ...$curr["children_rec"]);
}
}
print_r($flattened);
Array
(
[0] => Shirt
[1] => Plain
[2] => T-Shirt
[3] => Plain
[4] => Classic
[5] => Lycra
)
If order is important, you can array_reverse all arrays as you push them onto the stack without harming the linear time complexity.
For the updated specification, just plop the above code into a function and call it for each root node:
<?php
function flatten($tree) {
for ($stack = array_reverse($tree); !empty($stack);) {
$curr = array_pop($stack);
$flattened[] = $curr["id"];
if (!empty($curr["children_rec"])) {
array_push($stack, ...array_reverse($curr["children_rec"]));
}
}
return $flattened;
}
$tree = json_decode('[ { "id": 1, "name": "T-Shirt", "children_rec": [ { "id": 2, "name": "Classic", "children_rec": [ { "id": 3, "name": "Lycra", "children_rec": [] } ] }, { "id": 4, "name": "Plain", "children_rec": [] } ] }, { "id": 5, "name": "Shirt", "children_rec": [ { "id": 6, "name": "Plain", "children_rec": [] } ] } ]', true);
foreach ($tree as &$root) {
$root["children"] = flatten($root["children_rec"]);
unset($root["children_rec"]);
}
echo json_encode($tree, JSON_PRETTY_PRINT)."\n";
Output:
[
{
"id": 1,
"name": "T-Shirt",
"children": [
2,
3,
4
]
},
{
"id": 5,
"name": "Shirt",
"children": [
6
]
}
]

json decode error on some requests but not others with Algolia php library

I'm seeing the following error:
My params are
array (size=4)
'facets' => string 'Instock.1' (length=9)
'facetFilters' => string 'inStock.1:1' (length=11)
'numericFilters' => string 'itemId!=511283' (length=14)
'getRankingInfo' => int 1
If I remove either getRankingInfo or numericFilters, it works for all requests.
According to the logs in Algolia it's returning results, but i don't get that far on my end for some requests.
One response that causes the error to appear is:
Request
{
"params": "facets=Instock.1&facetFilters=inStock.1%3A1&numericFilters=itemId%21%3D511283&getRankingInfo=1&query=WARBURTON+ORANGE+WRAPPER+800G"
}
Response
{
"hits": [
{
"itemId": 506241,
"name": "Warburton Blue Wrapper 800g",
"slug": "506241-warburton-blue-wrapper",
"brand": "Warburton",
"supplier_name": "Warburtons Bread",
"size": "800G",
"status": "L",
"vat_rate": "0.00",
"popularity": 18992,
"image": "/images/products/506241.jpg",
"thumbnail": "/images/products/506241_thumbnail.jpg",
"barcodes": [
"5010044000039"
],
"branches": [
1,
2,
4,
5,
6
],
"deepestCategory": "07013033337",
"inStock": {
"1": 1,
"2": 0,
"4": 1,
"5": 1,
"6": 1
},
"alternatives": [
],
"objectID": "506241",
"_highlightResult": {
"name": {
"value": "<em>Warburton</em> Blue <em>Wrapper</em> <em>800g</em>",
"matchLevel": "partial",
"matchedWords": [
"warburton",
"wrapper",
"800g"
]
},
"barcodes": [
{
"value": "5010044000039",
"matchLevel": "none",
"matchedWords": [
]
}
]
},
"_rankingInfo": {
"nbTypos": 0,
"firstMatchedWord": 0,
"proximityDistance": 10,
"userScore": 21542,
"geoDistance": 0,
"geoPrecision": 1,
"nbExactWords": 3,
"words": 3
}
},
{
"itemId": 511294,
"name": "Warburton Green Wrapper ",
"slug": "511294-warburton-green-wrapper",
"brand": "Warburton",
"supplier_name": "Warburtons Bread",
"size": "",
"status": "L",
"vat_rate": "0.00",
"popularity": 78098,
"image": "/images/products/511294.jpg",
"thumbnail": "/images/products/511294_thumbnail.jpg",
"barcodes": [
"5010044002347"
],
"branches": [
1,
2,
4,
5,
6
],
"deepestCategory": "07013033337",
"inStock": {
"1":
One that works fine is:
Request body
{
"params": "facets=Instock.1&facetFilters=inStock.1%3A1&numericFilters=itemId%21%3D558471&getRankingInfo=1&query=I+CAN%27T+BELIEVE+IT%27S+NOT+BUTTER+2KG"
}
Response
{
"hits": [
{
"itemId": 581691,
"name": "I Can't Believe Its Not Butter 500g",
"slug": "581691-i-cant-believe-its-not-butter",
"brand": "I Can't Believe",
"supplier_name": "U.lever Bestfoods (chilled)",
"size": "500G",
"status": "L",
"vat_rate": "0.00",
"popularity": 36597,
"image": "/images/products/581691.jpg",
"thumbnail": "/images/products/581691_thumbnail.jpg",
"barcodes": [
"000118039904",
"05000118039904",
"5000241007009"
],
"branches": [
1,
2,
3,
4,
5,
6
],
"deepestCategory": "07015269103",
"inStock": {
"1": 1,
"2": 1,
"3": 1,
"4": 1,
"5": 1,
"6": 1
},
"alternatives": [
],
"objectID": "581691",
"_highlightResult": {
"name": {
"value": "<em>I</em> <em>Can't</em> <em>Believe</em> <em>Its</em> <em>Not</em> <em>Butter</em> 500g",
"matchLevel": "partial",
"matchedWords": [
"i",
"can",
"t",
"believe",
"it",
"s",
"not",
"butter"
]
},
"barcodes": [
{
"value": "000118039904",
"matchLevel": "none",
"matchedWords": [
]
},
{
"value": "05000118039904",
"matchLevel": "none",
"matchedWords": [
]
},
{
"value": "5000241007009",
"matchLevel": "none",
"matchedWords": [
]
}
]
},
"_rankingInfo": {
"nbTypos": 0,
"firstMatchedWord": 0,
"proximityDistance": 22,
"userScore": 15914,
"geoDistance": 0,
"geoPrecision": 1,
"nbExactWords": 6,
"words": 8
}
},
{
"itemId": 247577,
"name": "I Can't Believe Its Not Butter 250g"
It seems the result set was causing an error with json_decode. When I limited the hitsPerPage to 10 all works fine. So the answer here is to paginate large sets, obvious really.
Thanks to all who read and commented.

Get information from multidimensional json in php

I am trying to get back information from a multidimensional json array but can't seem to get it right.
Below is an example of the output from the url which you can see yourself at http://109.255.189.130:3000/
{ "vnc_version": "2.1.0.0", "mod_version": "1.0.0.0", "server": { "name": "Pure Blood", "framework": "Microsoft Windows NT 6.2.9200.0" }, "stats": { "uptime": 53462.0, "uptime_peak": 53462.0, "online": 1, "online_max": 1, "online_peak": 2, "unique": 1, "unique_max": 1, "unique_peak": 2, "items": 111752, "items_max": 112259, "items_peak": 112259, "mobiles": 37963, "mobiles_max": 37976, "mobiles_peak": 37978, "guilds": 0, "guilds_max": null, "guilds_peak": 0 }, "players": [ { "info": { "id": 1, "name": "aN.Droid", "title": "", "profile": "", "guild_id": -1, "guild_abbr": "" }, "stats": [ ], "skills": [ ], "equip": [ ] } ], "guilds": [ ] }
What I would like to do is echo the name in the players array. There will be more than one player.
Can anyone please help me out here and point me in the correct direction to get this information?
I am very new to json so excuse my ignorance on the subject.
Thank you!
<?php
$json = '{ "vnc_version": "2.1.0.0", "mod_version": "1.0.0.0", "server": { "name": "Pure Blood", "framework": "Microsoft Windows NT 6.2.9200.0" }, "stats": { "uptime": 54383.3, "uptime_peak": 54383.3, "online": 1, "online_max": 1, "online_peak": 2, "unique": 1, "unique_max": 1, "unique_peak": 2, "items": 111672, "items_max": 112259, "items_peak": 112259, "mobiles": 37944, "mobiles_max": 37976, "mobiles_peak": 37978, "guilds": 0, "guilds_max": null, "guilds_peak": 0 }, "players": [ { "info": { "id": 1, "name": "aN.Droid", "title": "", "profile": "", "guild_id": -1, "guild_abbr": "" }, "stats": [ ], "skills": [ ], "equip": [ ] } ], "guilds": [ ] }';
$array = json_decode($json, true);
// you want 'true' as the second parameter so it tunrs this JSON data into a multidimensional array instead of objects.
foreach($array['players'] as $player){
print_r($player['info']);
//etc.. do what you want with each player
}
$json = '{ "vnc_version": "2.1.0.0", "mod_version": "1.0.0.0", "server": { "name": "Pure Blood", "framework": "Microsoft Windows NT 6.2.9200.0" }, "stats": { "uptime": 53462.0, "uptime_peak": 53462.0, "online": 1, "online_max": 1, "online_peak": 2, "unique": 1, "unique_max": 1, "unique_peak": 2, "items": 111752, "items_max": 112259, "items_peak": 112259, "mobiles": 37963, "mobiles_max": 37976, "mobiles_peak": 37978, "guilds": 0, "guilds_max": null, "guilds_peak": 0 }, "players": [ { "info": { "id": 1, "name": "aN.Droid", "title": "", "profile": "", "guild_id": -1, "guild_abbr": "" }, "stats": [ ], "skills": [ ], "equip": [ ] } ], "guilds": [ ] }';
$arr = json_decode($json, true);
foreach($arr["players"] as $player) print($player["info"]["name"]."<br/>");

Categories