I'm really having trouble displaying JSON data with groupBy user_id conditions on the same data and displaying multiple data on certain data.
My Table:
---- --------- ------------ ------------ ------------- ------- -------
| id | user_id | contact_id | product_id | category_id | grade | point |
---- --------- ------------ ------------ ------------- ------- -------
| 1 | 9788 | 10083 | 1 | 23 | A | 89 |
---- --------- ------------ ------------ ------------- ------- -------
| 2 | 9788 | 10083 | 2 | 27 | A | 89 |
---- --------- ------------ ------------ ------------- ------- -------
PHP Script:
$arr = [];
foreach($data as $value){
$arr['user_id'] = $value['user_id'];
$arr['contact_id'] = $value['contact_id'];
$arr[$value['product_id']]['attributes']['products'] = $value['product_id'];
$arr[$value['category_id']]['attributes']['products'] = $value['category_id'];
$arr['grade'] = $value['grade'];
$arr['point'] = $value['point'];
}
The JSON output what I want:
"user_id" : 9788,
"contact_id" : 10083
"attributes": [
{
"products": [
{
"product_id": "1",
"category_id": "23"
},
{
"product_id": "2",
"category_id": "27"
}
]
}
],
"grade" : "A",
"point" : 89
The current output is:
{
"2": { "attributes": { "products": 1 } },
"4": { "attributes": { "products": 23 } },
"21": { "attributes": { "products": 2 } },
"25": { "attributes": { "products": 27 } },
"user_id": 9788,
"contact_id": 10083,
"grade": "A",
"point": 89
}
CodePudding user response:
first of all you should create a products sub array, then put into it product_id and category_id
$arr = [];
foreach($data as $value){
$arr['user_id'] = $value['user_id'];
$arr['contact_id'] = $value['contact_id'];
if(!isset($arr[$value['product_id']]['attributes']['products']))
$arr[$value['product_id']]['attributes']['products'] = [];//if the sub array not created so create it
$arr[$value['product_id']]['attributes']['products'][] = [
"product_id"=>$value['product_id'],
"category_id"=>$value['category_id']
];//add new element in the products array
$arr['grade'] = $value['grade'];
$arr['point'] = $value['point'];
}
CodePudding user response:
That seems a good use case for the PHP
's built-in function array_reduce
.
The process is rather simple and straightforward, loop through the array and group the same product_id
values inside a new key (to be added) that you've called attributes
.
/** that's the initial array (based on the table found in the OP's question) */
$arr = [
[
'id' => 1,
'user_id' => 9788,
'contact_id' => 10083,
'product_id' => 1,
'category_id' => 23,
'grade' => 'A',
'point' => 89,
],
[
'id' => 1,
'user_id' => 9788,
'contact_id' => 10083,
'product_id' => 2,
'category_id' => 27,
'grade' => 'A',
'point' => 89,
]
];
/** the grouped array which will hold "array_reduce" result */
$groupedArr = array_reduce($arr, function ($a, $c) {
/**
* we need to group the resulting array by the "user_id" key
* to ensure that the products are correctly grrouped later on
* we can easily get rid of that outer key later on
*/
$a[$c['user_id']] = [
'user_id' => $c['user_id'],
'contact_id' => $c['contact_id'],
/**
* merge the "attributes" that are found in the resulting array at this moment plus the current iteration's values
* the function "array_merge" will take care of that part
*/
'attributes' => array_merge([[
'product_id' => $c['product_id'],
'category_id' => $c['category_id']
]], $a[$c['user_id']]['attributes'] ?? []),
'grade' => $c['grade'],
'point' => $c['point']
];
/** return the array so the next iteration could work based on it */
return $a;
}, []);
At this point, $groupedArr
should hold the following data:
echo var_export($groupedArr); // prints:
/**
[
9788 => [
'user_id' => 9788,
'contact_id' => 10083,
'attributes' => [
['product_id' => 2, 'category_id' => 27],
['product_id' => 1, 'category_id' => 23]
],
'grade' => 'A',
'point' => 89
]
];
*/
Now, as it seems, you need to convert the result to JSON
without having the outer keys (9788
in the above result print). To do so we can use [array_values][2]
to strip those top keys and then we may call json_encode
to have our JSON
:
echo json_encode(array_values($groupedArr)); // prints:
/**
[
{
"user_id": 9788,
"contact_id": 10083,
"attributes": [
{
"product_id": 2,
"category_id": 27
},
{
"product_id": 1,
"category_id": 23
}
],
"grade": "A",
"point": 89
}
]
*/
And here's a live demo to illustrate what's have been said.