Simplify & Optimize PHP Array - php

I am working on combining the array into a key with the count of repeated "option""code". My Request JSON is like this
[{
"productId": "DENSUS-MARK",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE"
},
{
"code": "HIGLIGT_OPTION_HANDLE1"
}
]
},
{
"productId": "DENSUS-MARK",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE"
}
]
},
{
"productId": "DENSUS-MARK-II",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE"
}
]
}]
After combing the "productID" and the count of ["options"]["code"] (For ProductId - DENSUS-MARK, the code "HIGLIGT_OPTION_HANDLE" count is 2. So I am getting a output like this.
{
"productId": "DENSUS-MARK",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE",
"count": 2
},
{
"code": "HIGLIGT_OPTION_HANDLE1",
"count": 1
}
]
},
{
"productId": "DENSUS-MARK-II",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE",
"count": 1
}
]
}
}
This is my current php code and I need to optimize & simply this below code
$datas = json_decode($arr,true);
$formattedData = [];
foreach ($datas as $f) {
foreach ($f['options'] as $option) {
$formattedData[$f['productID']]['productID'] = $f['productID'];
$formattedData[$f['productID']]['options']['code'][$option['code']][] = $option['code'];
}
}
foreach ($formattedData as &$data) {
$formattedOptions = [];
foreach ($data['options']['code'] as $key => $codes) {
$formattedOptions[] = [
'code' => $key,
'count' => count($codes)
];
}
$data = $formattedOptions;
}
print_r($formattedData);
Someone, could you please help me in this.

I don't know if this is the optimization you want. Meanwhile, less than two loops, I have not found. It's not quite the expected result, but you should be able to fix it if you need to.
With:
$input = array (
0 =>
array (
'productId' => 'DENSUS-MARK',
'options' =>
array (
0 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE',
),
1 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE1',
),
),
),
1 =>
array (
'productId' => 'DENSUS-MARK',
'options' =>
array (
0 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE',
),
),
),
2 =>
array (
'productId' => 'DENSUS-MARK-II',
'options' =>
array (
0 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE',
),
),
)
);
Then just:
$result = [];
foreach($input as $row) {
foreach($row['options'] as $value) {
$result[$row['productId']][$value['code']] ??=0;
$result[$row['productId']][$value['code']] += count($value);
}
}
var_export($result);
Results:
array (
'DENSUS-MARK' =>
array (
'HIGLIGT_OPTION_HANDLE' => 2,
'HIGLIGT_OPTION_HANDLE1' => 1,
),
'DENSUS-MARK-II' =>
array (
'HIGLIGT_OPTION_HANDLE' => 1,
),
)

Related

Display data from two arrays having one common point

I have two arrays.
The first one is about exchange-rate and the display in my console is like this :
{
"exchange_rate": [
{
"id": "978",
"start_dateTime": "2021-08-01 07:35:02",
"target_value": "1.00000",
"currency_value_euro": "0.84097",
"currency_value_dollar_us": "1.00000",
"id_currency": "1",
"currency": "Dollar am\u00e9ricain",
"currency_symbol": "$US"
},
{
"id": "980",
"start_dateTime": "2021-08-01 07:35:02",
"target_value": "1.00000",
"currency_value_euro": "1.17454",
"currency_value_dollar_us": "0.71600",
"id_currency": "2",
"currency": "Livre sterling",
"currency_symbol": "\u00a3"
}
]
}
These data came from the database and I can display it by choosing particular dates with jQuery.
The second array contains only id_currency which in my console is like this : Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5
On my website, I want to be able to display specific exchange rate by specific currency and dates.
And here my problem appears, I can't find the way to loop on the first array, and loop again inside, on the second array and compare both like if first array has id_currency 1 and second array has id_currency 1 then display the complete line from first array.
I've tried several things but nothing works, at last i've tried this :
foreach ($res as $row){
$idBDD = $row['id_currency'];
$symbolBDD = $row['currency_symbol'];
echo $idBDD;
echo $symbolBDD;
//var_dump($row);
/*foreach ($arr as $line){
$idCheckbox = $line;
echo $idCheckbox;
}
if ($idBDD == $idCheckbox){
echo 'fine';
}
*/
}
I'll be grateful for your help
You need to access the array with $res["exchange_rate"] and loop through it then.
<?php
$res = [
"exchange_rate" => [
[
"id" => "978",
"start_dateTime" => "2021-08-01 07:35:02",
"target_value" => "1.00000",
"currency_value_euro" => "0.84097",
"currency_value_dollar_us" => "1.00000",
"id_currency" => "1",
"currency" => "Dollar américain",
"currency_symbol" => "\$US"
],
[
"id" => "980",
"start_dateTime" => "2021-08-01 07:35:02",
"target_value" => "1.00000",
"currency_value_euro" => "1.17454",
"currency_value_dollar_us" => "0.71600",
"id_currency" => "2",
"currency" => "Livre sterling",
"currency_symbol" => "£"
]
]
];
$output = null;
foreach ($res["exchange_rate"] as $row) {
if (!isset($output)) {
$output = $row;
}
$output = array_intersect_assoc($output, $row);
}
var_dump($output);
I think you could do it like this, of course if you're inside the loop, you won't need to put indices.
read more array_diff()
https://www.php.net/manual/pt_BR/function.array-diff.php
$array = [
"exchange_rate" => [
[
"id" => "978",
"start_dateTime" => "2021-08-01 07:35:02",
"target_value"=> "1.00000",
"currency_value_euro"=> "0.84097",
"currency_value_dollar_us"=> "1.00000",
"id_currency"=> "1",
"currency"=> "Dollar am\u00e9ricain",
"currency_symbol" => "US"
],[
"id"=> "980",
"start_dateTime"=> "2021-08-01 07=> 35=> 02",
"target_value"=> "1.00000",
"currency_value_euro"=> "1.17454",
"currency_value_dollar_us"=> "0.71600",
"id_currency"=> "2",
"currency"=> "Livre sterling",
"currency_symbol"=> "\u00a3"
]
]
];
$array1 = $array['exchange_rate'][0];
$array2 = $array['exchange_rate'][1];
$result = array_diff( $array1, $array2);
var_dump($result);

Transpose subarray data from indexed to associative

I'm making an API for getting some data. My API gives object data like given, given object I wanted to format some data inside object:
{
"data": [
{
"productId": 55,
"productTitle": "Test product",
"variation": {
"Color": "Red",
"Size": "XS",
"din": "10190537",
"product_id": 55,
"name": [
"Color",
"Size"
],
"value": [
"Red",
"XS"
]
},
"din": "10190537",
"markets": [
{
"id": 11,
"name": "paytmmall",
"displayName": "PayTm Mall",
"identifierName": "Product_Id"
}
]
}
]
}
In this object I want data like given
{
"data": [
{
"productId": 55,
"productTitle": "this is test from hariom",
"variation": {
"Color": "Red",
"Size": "XS",
"din": "10190537",
"product_id": 55,
"variationTypes": [
{
"name": "Color",
"value": "Red"
},
{
"name": "Size",
"value": "XS"
}
],
},
"din": "10190537",
"markets": [
{
"id": 11,
"name": "paytmmall",
"displayName": "PayTm Mall",
"identifierName": "Product_Id"
}
]
}
]
}
Here Is my Controller Name
public function MarketMapping(Request $request)
{
$sellerId = Auth::guard('seller-api')->user();
$page = $request->has('pageNumber') ? $request->get('pageNumber') : 1;
$limit = $request->has('perPage') ? $request->get('perPage') : 10;
$variationFromInvTbl = ProductInventory::select('Color', 'Size', 'din', 'product_id')->where('seller_id', $sellerId->id)->where('status', 'active')->limit($limit)->offset(($page - 1) * $limit)->get();
$dataArray = array();
foreach($variationFromInvTbl as $key => $varitionValue)
{
$prodtsFromLivetbl = ProductsLive::select('productTitle', 'product_id')->where('product_id', $varitionValue->product_id)->get();
foreach ($prodtsFromLivetbl as $key => $value)
{
$marketChannelData = DB::table('market_channels')
->join('sellers_market_channels', 'market_channels.name', '=', 'sellers_market_channels.key')
//->join('market_product_mappings', 'market_channels.id', '=', 'market_product_mappings.market_id')
->select('market_channels.id','market_channels.name', 'market_channels.displayName','market_channels.identifierName') //'market_product_mappings.identifierValue'
->where('sellers_market_channels.seller_id', $sellerId->id)
->where('sellers_market_channels.value', 1)
->get();
$maketProductMap = MarketProductMapping::where('seller_id', $sellerId->id)->where('product_id', $varitionValue->product_id)->where('din', $varitionValue->din)->pluck('identifierValue');
if (count($maketProductMap))
{
$marketChannelData[$key]->value = $maketProductMap[0];
}
$varitionValue['name']= array_keys($varitionValue->only(['Color', 'Size']));
$varitionValue['value'] = array_values($varitionValue->only(['Color', 'Size']));
$dataObject = ((object)[
"productId" => $value->product_id,
"productTitle" => $value->productTitle,
"variation" => $varitionValue,
"din" => $varitionValue['din'],
"markets" => $marketChannelData
]);
array_push($dataArray,$dataObject);
}
}
if($variationFromInvTbl)
{
$response['success'] = true;
$response["page"] = $page;
$response["itemPerPage"] = $limit;
$response["totalRecords"] = $this->CountMarketMapping($page, $limit, $sellerId->id);
$response['data'] = $dataArray;
return response()->json($response, 200);
}else{
$response['success'] = false;
$response['data'] = $prodtsFromLivetbl;
return response()->json($response, 409);
}
}
You are using laravel's only() method which returns an associative array.
You wish to convert each key-value pair into a subarray containing two associative elements -- the original key will be the value of the name element
and the original value will be the value of the value element.
By passing the original array keys and array values into array_map(), you can iterate them both synchronously.
compact() is a perfect native function to create the desired associative subarrays from the iterated parameters.
Code: (Demo)
$variations = $varitionValue->only(['Color', 'Size']);
$dataObject = (object)[
// ... your other data
'variations' => array_map(
function($name, $value) {
return compact(['name', 'value']);
},
array_keys($variations),
$variations
),
// ...your other data
];
var_export($dataObject);
Output:
(object) array(
'variations' =>
array (
0 =>
array (
'name' => 'Color',
'value' => 'Red',
),
1 =>
array (
'name' => 'Size',
'value' => 'XS',
),
),
)
This script will help you
<?php
$data = [
"variation" => [
[
"Color" => "Red",
"Size" => "XS",
"din" => "10190537",
"product_id" => 55,
"name" => [
"0" => "Color",
"1" => "Size"
],
"value" => [
"0" => "Red",
"1" => "XS"
]
]
]
];
for ($i=0; $i < count($data["variation"]); $i++) {
$data["variation"][$i]["data"]["name"] = $data["variation"][$i]["name"];
$data["variation"][$i]["data"]["value"] = $data["variation"][$i]["value"];
unset($data["variation"][$i]["name"]);
unset($data["variation"][$i]["value"]);
}
print_r($data);
output
Array
(
[variation] => Array
(
[0] => Array
(
[Color] => Red
[Size] => XS
[din] => 10190537
[product_id] => 55
[data] => Array
(
[name] => Array
(
[0] => Color
[1] => Size
)
[value] => Array
(
[0] => Red
[1] => XS
)
)
)
)
)

PHP Add null to array value if it doesn't exist

I'm generating data arrays and want to add 0/null to a specific month, where no data is present, but been struggling with it for few days.
I'm generating the final dataset array like this
foreach ($patients as $key => $item) {
$labels[] = $item['month'];
usort($labels, "compare_months");
$labels = array_unique($labels);
$chartData[ $item['brand_name'] ]['data'][] =
$item['patientsCount'];
$chartData[ $item['brand_name'] ]['brand_data'] = [
"name" => $item['brand_name'],
"color" => $item['color']
];
}
foreach ($chartData as $item) {
$pointRadius++;
$dataSet[] = [
'label' => $item['brand_data']['name'],
'data' => $item['data'],
'pointRadius' => $pointRadius,
'fill' => false,
'borderWidth' => 1,
'backgroundColor' => "#" . $item['brand_data']['color'],
'borderColor' => "#" . $item['brand_data']['color'],
];
}
$finalData[] = [
'labels' => $labels,
'datasets' => $dataSet
];
Which gives me this json response
[
{
"labels":[
"April",
"May",
"June",
"July"
],
"datasets":[
{
"label":"Medicine 1",
"data":[
1
],
"pointRadius":1,
"fill":false,
"borderWidth":1,
"backgroundColor":"#ea5f2d",
"borderColor":"#ea5f2d"
},
{
"label":"Medicine 2",
"data":[
1,
1,
1
],
"pointRadius":2,
"fill":false,
"borderWidth":1,
"backgroundColor":"#ffb400",
"borderColor":"#ffb400"
},
{
"label":"Medicine 3",
"data":[
1,
1,
2
],
"pointRadius":3,
"fill":false,
"borderWidth":1,
"backgroundColor":"#ff7777",
"borderColor":"#ff7777"
},
{
"label":"Medicine 4",
"data":[
1,
1,
2
],
"pointRadius":4,
"fill":false,
"borderWidth":1,
"backgroundColor":"#64a36f",
"borderColor":"#64a36f"
},
{
"label":"Medicine 5",
"data":[
2
],
"pointRadius":5,
"fill":false,
"borderWidth":1,
"backgroundColor":"#e7e6fc",
"borderColor":"#e7e6fc"
}
]
}
]
As you can see, for some items, the data object only contains 1 value which is wrong, because I need to add zeros to months, where there is no data.
Can this be done in MySQL or is it better to use PHP and how?
EDIT 1
Here is the array I am currently getting.
Array
(
[MEDICINE 1] => Array
(
[April] => 1
)
[MEDICINE 2] => Array
(
[April] => 1
[July] => 2
)
[MEDICINE 3] => Array
(
[April] => 1
[May] => 1
[July] => 2
)
[MEDICINE 4] => Array
(
[May] => 1
[July] => 3
)
[MEDICINE 5] => Array
(
[June] => 2
)
[MEDICINE 6] => Array
(
[July] => 1
)
)
As you can see some medicines have data for only one month and I want to add these months to the medicine array with 0 value, if there is no data.
Add this line after each foreach: if (count($item['data']) < 2) continue;. Because you need skip if length of data is smaller than 2.
foreach ($patients as $key => $item) {
if (count($item['data']) < 2) continue;
$labels[] = $item['month'];
usort($labels, "compare_months");
$labels = array_unique($labels);
$chartData[ $item['brand_name'] ]['data'][] =
$item['patientsCount'];
$chartData[ $item['brand_name'] ]['brand_data'] = [
"name" => $item['brand_name'],
"color" => $item['color']
];
}
foreach ($chartData as $item) {
$pointRadius++;
if (count($item['data']) < 2) continue;
$dataSet[] = [
'label' => $item['brand_data']['name'],
'data' => $item['data'],
'pointRadius' => $pointRadius,
'fill' => false,
'borderWidth' => 1,
'backgroundColor' => "#" . $item['brand_data']['color'],
'borderColor' => "#" . $item['brand_data']['color'],
];
}
$finalData[] = [
'labels' => $labels,
'datasets' => $dataSet
];

Remove from multidimensional array if has seen id before in an basic array

I would like in php to stop duplicate messages by logging msgid to a text file using something like this file_put_contents("a.txt", implode(PHP_EOL, $array1), FILE_APPEND);
and then converting it back to an array using $array1 = file("a.txt"); I would also like to delete messages from the array if they are from a set name
I know how to convert json to an array $array1 = json_decode($json, true);
Json Reply from an api that I cannot control
{
"API": "Online",
"MSG": [
{
"info": {
"name": "example"
},
"msg": "example",
"msgid": "example"
},
{
"info": {
"name": "example"
},
"msg": "example",
"msgid": "example"
}
]
}
Hi use the following code, first test it out accordingly
$uniqueMessages = unique_multidim_array($messages,'msg');
Usage : Pass the key as the 2nd parameter for which you need to check the uniqueness of array.
<?php
/* Function to handle unique assocative array */
function unique_multidim_array($array, $key) {
/* temp array to hold unique array */
$temp_array = array();
/* array to hold */
$i = 0;
/* array to hold the key for unique array */
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
$messages = array(
0 => array(
'info' => array(
'name' => 'example'
),
'msg' => 'example',
'msgid' => 'example'
),
1 => array(
'info' => array(
'name' => 'example 1'
),
'msg' => 'example 1',
'msgid' => 'example 1'
),
3 => array(
'info' => array(
'name' => 'example'
),
'msg' => 'example',
'msgid' => 'example'
)
);
echo '<pre>';
echo '*****************BEFORE***********************<br/>';
var_dump($messages);
echo '*****************AFTER***********************<br/>';
$uniqueMessages = unique_multidim_array($messages,'msg');
var_dump($uniqueMessages);
This works for me this is an modded function click here for original function
function RemoveElementByArray($array, $key, $seen){
foreach($array as $subKey => $subArray){
if(in_array($subArray[$key], $seen)){
unset($array[$subKey]);
}
}
return $array;
}
Example:
$array = array(
array("id" => "1", "name" => "example1"),
array("id" => "2", "name" => "example2"),
array("id" => "3", "name" => "example3"));
$SeenArray = array("1", "2");
print_r(RemoveElementByArray($array, "id", $SeenArray));
Result:
Array
(
[2] => Array
(
[id] => 3
[name] => example3
)
)

PHP Create a Multidimensional Array from an array with relational data [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Converting an array from one to multi-dimensional based on parent ID values
I am working in PHP.
I have the following array that has relational data (parent child relationships).
Array
(
[5273] => Array
(
[id] => 5273
[name] => John Doe
[parent] =>
)
[6032] => Array
(
[id] => 6032
[name] => Sally Smith
[parent] => 5273
)
[6034] => Array
(
[id] => 6034
[name] => Mike Jones
[parent] => 6032
)
[6035] => Array
(
[id] => 6035
[name] => Jason Williams
[parent] => 6034
)
[6036] => Array
(
[id] => 6036
[name] => Sara Johnson
[parent] => 5273
)
[6037] => Array
(
[id] => 6037
[name] => Dave Wilson
[parent] => 5273
)
[6038] => Array
(
[id] => 6038
[name] => Amy Martin
[parent] => 6037
)
)
I need it to be in this JSON format:
{
"id":"5273",
"name":"John Doe",
"data":{
},
"children":[
{
"id":" Sally Smith",
"name":"6032",
"data":{
},
"children":[
{
"id":"6034",
"name":"Mike Jones",
"data":{
},
"children":[
{
"id":"6035",
"name":"Jason Williams",
"data":{
},
"children":[
{
"id":"node46",
"name":"4.6",
"data":{
},
"children":[
]
}
]
}
]
},
{
"id":"6036",
"name":"Sara Johnson",
"data":{
},
"children":[
]
},
{
"id":"6037",
"name":"Dave Wilson",
"data":{
},
"children":[
{
"id":"6038",
"name":"Amy Martin",
"data":{
},
"children":[
]
}
]
}
]
}
]
}
I know I need to create a multidimensional array and run it through json_encode(). I also believe this method used to do this needs to be recursive because the real world data could have an unknown number of levels.
I would be glad to show some of my approaches but they have not worked.
Can anyone help me?
I was asked to share my work. This is what I have tried but I have not gotten that close to I don't know how helpful it is.
I made an array of just the relationships.
foreach($array as $k => $v){
$relationships[$v['id']] = $v['parent'];
}
I think (based off another SO post) used this relational data to create a the new multidimensional array. If I got this to work I was going to work on adding in the correct "children" labels etc.
$childrenTable = array();
$data = array();
foreach ($relationships as $n => $p) {
//parent was not seen before, put on root
if (!array_key_exists($p, $childrenTable)) {
$childrenTable[$p] = array();
$data[$p] = &$childrenTable[$p];
}
//child was not seen before
if (!array_key_exists($n, $childrenTable)) {
$childrenTable[$n] = array();
}
//root node has a parent after all, relocate
if (array_key_exists($n, $data)) {
unset($data[$n]);
}
$childrenTable[$p][$n] = &$childrenTable[$n];
}
unset($childrenTable);
print_r($data);
<?php
header('Content-Type: application/json; charset="utf-8"');
/**
* Helper function
*
* #param array $d flat data, implementing a id/parent id (adjacency list) structure
* #param mixed $r root id, node to return
* #param string $pk parent id index
* #param string $k id index
* #param string $c children index
* #return array
*/
function makeRecursive($d, $r = 0, $pk = 'parent', $k = 'id', $c = 'children') {
$m = array();
foreach ($d as $e) {
isset($m[$e[$pk]]) ?: $m[$e[$pk]] = array();
isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
$m[$e[$pk]][] = array_merge($e, array($c => &$m[$e[$k]]));
}
return $m[$r][0]; // remove [0] if there could be more than one root nodes
}
echo json_encode(makeRecursive(array(
array('id' => 5273, 'parent' => 0, 'name' => 'John Doe'),
array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
)));
demo: https://3v4l.org/s2PNC
Okay, this is how it works, you were actually not too far off as you started, but what you actually look for are references. This is a general procedure:
As there is a relation between parent and child-nodes on their ID, you first need to index the data based on the ID. I do this here with an array ($rows) to simulate your data access, if you read from the database, it would be similar. With this indexing you can also add additional properties like your empty data:
// create an index on id
$index = array();
foreach($rows as $row)
{
$row['data'] = (object) array();
$index[$row['id']] = $row;
}
So now all entries are indexed on their ID. This was the first step.
The second step is equally straight forward. Because we now can access each node based on it's ID in the $index, we can assign the children to their parent.
There is one "virtual" node, that is the one with the ID 0. It does not exists in any of the rows, however, if we could add children to it too, we can use this children collection as the store for all root nodes, in your case, there is a single root node.
Sure, for the ID 0, we should not process the parent - because it does not exists.
So let's do that. We make use of references here because otherwise the same node could not be both parent and child:
// build the tree
foreach($index as $id => &$row)
{
if ($id === 0) continue;
$parent = $row['parent'];
$index[$parent]['children'][] = &$row;
}
unset($row);
Because we use references, the last line takes care to unset the reference stored in $row after the loop.
Now all children have been assigned to their parents. That could it be already, however lets not forget the last step, the actual node for the output should be accessed.
For brevity, just assign the root node to the $index itself. If we remember, the only root node we want is the first one in the children array in the node with the ID 0:
// obtain root node
$index = $index[0]['children'][0];
And that's it. We can use it now straight away to generate the JSON:
// output json
header('Content-Type: application/json');
echo json_encode($index);
Finally the whole code at a glance:
<?php
/**
* #link http://stackoverflow.com/questions/11239652/php-create-a-multidimensional-array-from-an-array-with-relational-data
*/
$rows = array(
array('id' => 5273, 'parent' => 0, 'name' => 'John Doe'),
array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
);
// create an index on id
$index = array();
foreach($rows as $row)
{
$row['data'] = (object) [];
$index[$row['id']] = $row;
}
// build the tree
foreach($index as $id => &$row)
{
if ($id === 0) continue;
$parent = $row['parent'];
$index[$parent]['children'][] = &$row;
}
unset($row);
// obtain root node
$index = $index[0]['children'][0];
// output json
header('Content-Type: application/json');
echo json_encode($index, JSON_PRETTY_PRINT);
Which would create the following json (here with PHP 5.4s' JSON_PRETTY_PRINT):
{
"id": 5273,
"parent": 0,
"name": "John Doe",
"data": {
},
"children": [
{
"id": 6032,
"parent": 5273,
"name": "Sally Smith",
"data": {
},
"children": [
{
"id": 6034,
"parent": 6032,
"name": "Mike Jones",
"data": {
},
"children": [
{
"id": 6035,
"parent": 6034,
"name": "Jason Williams",
"data": {
}
}
]
}
]
},
{
"id": 6036,
"parent": 5273,
"name": "Sara Johnson",
"data": {
}
},
{
"id": 6037,
"parent": 5273,
"name": "Dave Wilson",
"data": {
},
"children": [
{
"id": 6038,
"parent": 6037,
"name": "Amy Martin",
"data": {
}
}
]
}
]
}
Following code will do the job.. you may want to tweak a bit according to your needs.
$data = array(
'5273' => array( 'id' =>5273, 'name'=> 'John Doe', 'parent'=>''),
'6032' => array( 'id' =>6032, 'name'=> 'Sally Smith', 'parent'=>'5273'),
'6034' => array( 'id' =>6034, 'name'=> 'Mike Jones ', 'parent'=>'6032'),
'6035' => array( 'id' =>6035, 'name'=> 'Jason Williams', 'parent'=>'6034')
);
$fdata = array();
function ConvertToMulti($data) {
global $fdata;
foreach($data as $k => $v)
{
if(empty($v['parent'])){
unset($v['parent']);
$v['data'] = array();
$v['children'] = array();
$fdata[] = $v;
}
else {
findParentAndInsert($v, $fdata);
}
}
}
function findParentAndInsert($idata, &$ldata) {
foreach ($ldata as $k=>$v) {
if($ldata[$k]['id'] == $idata['parent']) {
unset($idata['parent']);
$idata['data'] = array();
$idata['children'] = array();
$ldata[$k]['children'][] = $idata;
return;
}
else if(!empty($v['children']))
findParentAndInsert($idata, $ldata[$k]['children']);
}
}
print_r($data);
ConvertToMulti($data);
echo "AFTER\n";
print_r($fdata);
http://codepad.viper-7.com/Q5Buaz

Categories