Home > Mobile >  PHP Foreach, how to create multiple sub arrays and group the same data
PHP Foreach, how to create multiple sub arrays and group the same data

Time:09-22

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.

  • Related