Create an array of object PHP - php

I am trying to create this structure on PHP
and I don't know how to I create an array of object on PHP. It always get the last data from the object.
This is my current code:
array(
"description": getDescription($id),
"deposit": getPrices($id);
)
function getPrices($id) {
$test = Prices::where('price_id',$id)->where('promo',0)->get();
$price = [];
$data = [];
foreach($test as $t) {
$data["item_id"] = $t->id;
$data["price"] = $t->list;
$data["type"] = $t->type;
$price = $data;
}
return $price;
}

Fixing the actual issue with not receiving all records from the getPrices function:
array(
"description": getDescription($id),
"deposit": getPrices($id);
)
function getPrices($id) {
$test = Prices::where('price_id',$id)->where('promo',0)->get();
$price = [];
foreach($test as $t) {
$price[] = ["item_id" => $t->id, "price" => $t->list, "type": $t->type];
}
return $price;
}
You're missing the square brackets after $price (Correct: $price[]) variable which tells PHP to append to array rather than actually replace it.
The other option is to use array_push, which is more explicit but does the same; Read more here.
Fixing the issue of serialisation:
You can use json_encode to serialise the array into JSON (JavaScript Object Notation).

$dataArray=array();
foreach($test as $t) {
$dataArray[] = array('item'=> $t->id,'item'=> $t->price,'type'=> $t->type);
}
$finalArray= array('deposit'=>$dataArray);
convert final array to json using json_encode

$structure = new stdClass();
$structure->description = 'tobedefined'; // Define the description here
$structure->deposit = getPrices($id);
function getPrices($id) {
$deposits = array();
// Change this to contain the real data
// $test = Prices::where('price_id',$id)->where('promo',0)->get();
$test = array(
array(
'item_id' => 100,
'price' => '1, 2, 3, 4, 5',
'type' => 'child'
),
array(
'item_id' => 101,
'price' => '2, 4, 6, 8, 10',
'type' => 'child'
),
array(
'item_id' => 102,
'price' => '2, 4, 6, 8, 10',
'type' => 'child'
)
);
foreach ($test as $t) {
$deposit = new stdClass();
$deposit->item_id = $t['item_id'];
$deposit->price = $t['price'];
$deposit->type = $t['type'];
$deposits[] = $deposit;
}
return $deposits;
}
echo 'PHP Structure';
echo '<pre>';
print_r($structure);
echo '</pre>';
echo 'JSON string';
echo '<pre>';
print_r(json_encode($structure, JSON_PRETTY_PRINT));
echo '</pre>';
Output will be:
PHP Structure
stdClass Object
(
[description] => tobedefined
[deposit] => Array
(
[0] => stdClass Object
(
[item_id] => 100
[price] => 1, 2, 3, 4, 5
[type] => child
)
[1] => stdClass Object
(
[item_id] => 101
[price] => 2, 4, 6, 8, 10
[type] => child
)
[2] => stdClass Object
(
[item_id] => 102
[price] => 2, 4, 6, 8, 10
[type] => child
)
)
)
JSON string
{
"description": "tobedefined",
"deposit": [
{
"item_id": 100,
"price": "1, 2, 3, 4, 5",
"type": "child"
},
{
"item_id": 101,
"price": "2, 4, 6, 8, 10",
"type": "child"
},
{
"item_id": 102,
"price": "2, 4, 6, 8, 10",
"type": "child"
}
]
}

Related

PHP/MySQL - Nested groups in JSON

I'm creating nested (hierarchical) groups in JSON. The structure is simply - grand parent -> parent -> child:
main
secondary
mcondition
This is using the following MySQL/PHP to so far format main -> mcondition.
How should I change this to add the second level ('secondary' e.g. the parent level) between main and mcondition?
The column for secondary is mcondition.secondary
$query = 'SELECT * FROM mcondition ORDER BY mcondition.main ASC';
$result = $connection->query( $query );
$results = array();
$temp = array();
while ($line = mysqli_fetch_array($result)) {
$results[] = $line;
}
foreach($results as $row) {
$temp[$row['main']]['text'] = $row['main'];
if(!isset($temp[$row['main']]['children'])) {
$temp[$row['main']]['children'] = array();
}
array_push($temp[$row['main']]['children'], array(
'id' => $row['mcondition_pk'],
'text' => $row['mcondition_name']
));
}
$temp = array_values($temp);
echo json_encode($temp);
This is what the JSON currently looks like:
[
{
"text": "Main Heading 1",
"children": [
{
"id": "1",
"text": "mcondition_1"
},
{
"id": "17",
"text": "mcondition_4"
}
]
},
{
"text": "Main Heading 2",
"children": [
{
"id": "49",
"text": "mcondition_2"
},
{
"id": "48",
"text": "mcondition_5"
}
]
},
{
"text": "Main Heading 3",
"children": [
{
"id": "68",
"text": "mcondition_3"
},
{
"id": "67",
"text": "mcondition_6"
}
]
}
]
This is the structure of the table mcondition:
+---------------+------------+------+-----------+
| mcondition_pk | mcondition | main | secondary |
+---------------+------------+------+-----------+
Column mcondition is unique.
I'm still not 100% sure what your expected json would look like, but you should be able to do something like this. You may need to make some modifications to get exactly what you're wanting. I'm using an array $results to simulate the data acquisition from the database. This will get you a nested hierarchical structure.
$out = [];
$results = [
['main' => 'mk1', 'secondary' => 'sk1', 'mcondition_pk' => 1, 'mcondition' => 'mcondition_1'],
['main' => 'mk1', 'secondary' => 'sk2', 'mcondition_pk' => 2, 'mcondition' => 'mcondition_2'],
['main' => 'mk1', 'secondary' => 'sk2', 'mcondition_pk' => 3, 'mcondition' => 'mcondition_3'],
['main' => 'mk2', 'secondary' => 'sk3', 'mcondition_pk' => 4, 'mcondition' => 'mcondition_4'],
['main' => 'mk2', 'secondary' => 'sk3', 'mcondition_pk' => 5, 'mcondition' => 'mcondition_5'],
['main' => 'mk3', 'secondary' => 'sk4', 'mcondition_pk' => 6, 'mcondition' => 'mcondition_6'],
['main' => 'mk3', 'secondary' => 'sk5', 'mcondition_pk' => 7, 'mcondition' => 'mcondition_7'],
['main' => 'mk3', 'secondary' => 'sk5', 'mcondition_pk' => 8, 'mcondition' => 'mcondition_8'],
];
foreach($results as $row) {
$mk = $row['main'];
$sk = $row['secondary'];
$pk = $row['mcondition_pk'];
$cond = $row['mcondition'];
$temp = ['id' => $pk, 'text' => $cond];
if(!isset($out[$mk])) { $out[$mk] = ['text' => $mk]; }
if(!isset($out[$mk][$sk])) { $out[$mk][$sk] = ['text' => $sk, 'children' => []]; }
$out[$mk][$sk]['children'][] = $temp;
}
echo "<pre>"; print_r($out); echo "</pre>";
$json = json_encode($out);
echo "<pre>"; print_r($json); echo "</pre>"; exit;

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

Array search, add and delete

I have the following table:
CREATE TABLE sample (id INT AUTO_INCREMENT PRIMARY KEY, entry_id INT NOT NULL, last_change timestamp);
INSERT INTO sample (entry_id) VALUES (1), (2), (3), (4);
My code does the following:
Receives POST input and compares the values to the table above.
If the the POST data has a value that does not exist in the entry_id column, then it will perform an INSERT statement.
If the table has a value in the entry_id column that does not exist in the POST data, then it will perform a DELETE statement
PHP Code:
<?php
// $_POST data:
$submittedEntries = array(1, 3, 4, 5, 6);
// $dbORM->getEntries()
$currentEntries = array(
array("id" => 100, "entry_id" => 1, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 101, "entry_id" => 2, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 102, "entry_id" => 3, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 103, "entry_id" => 4, "timestamp" => "2014-07-24 2:14:00"),
)
$entriesToAdd = array();
$entriesToRemove = array();
// Find Entries to Add
// Loop through each entry submitted
foreach($submittedEntries as $entry_id) {
$exists = false;
// Loop through all Current Entries
foreach($currentEntries as $existingEntry) {
// Find matching IDs
if ($existingEntry["entry_id"] == $entry_id) {
$exists = true;
}
}
if ($exists == false) {
$entriesToAdd[] = $entry_id;
}
}
// Find Entries to Remove
// Loop through all Current Entries
foreach($currentEntries as $existingEntry) {
$remove = true;
// Loop through each entry submitted
foreach($submittedEntries as $entry_id) {
// Find matching IDs
if ($existingEntry["entry_id"] == $entry_id) {
$remove = false;
}
}
if ($remove == true) {
$entriesToRemove[] = $existingEntry["entry_id"];
}
}
// Add New Entries
foreach($entriesToAdd as $entry_id) {
$dbORM->addEntry($entry_id);
}
// Remove Entries
foreach($entriesToRemove as $entry_id) {
$dbORM->removeEntry($entry_id);
}
$entries = $dbORM->getEntries(); // SELECT * from sample;
print_r($entries);
/*
Expected Output:
array(
array("id" => 100, "entry_id" => 1, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 102, "entry_id" => 3, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 103, "entry_id" => 4, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 104, "entry_id" => 5, "timestamp" => "2014-07-24 3:27:00"),
array("id" => 105, "entry_id" => 6, "timestamp" => "2014-07-24 3:27:00")
)
*/
Is there a better way to do this? I looked into all the php array functions and they do not seem to be able to deep search of multidimensional arrays.
If the table has to always be exactly like the POST, simplest way is to DELETE all rows and then INSERT all posts.
Another solution could be the use of unique key on entry_id...
This way you could really simply do 2 small queries:
$insert = "INSERT IGNORE INTO sample (entry_id)VALUES(".implode('),(',$submittedEntries).")";
$delete = "DELETE FROM sample WHERE entry_id NOT IN(".implode(',',$submittedEntries).")";
If you want to compair the two lists in PHP then you can use array_walk() to run through the db list and then use in_array() to see if it's in the submitted POST. You can then filter into two arrays.
<?php
$entriesToAdd = array();
$entriesToRemove = array();
$submittedEntries = array(1, 3, 4, 5, 6);
$currentEntries = array(
array("id" => 100, "entry_id" => 1),
array("id" => 101, "entry_id" => 2),
array("id" => 102, "entry_id" => 3),
array("id" => 103, "entry_id" => 4),
);
function AWS(&$item, $key) {
global $submittedEntries, $entriesToAdd, $entriesToRemove;
if(in_array($item["entry_id"], $submittedEntries))
{
array_push($entriesToAdd, $item);
}
else
{
array_push($entriesToRemove, $item);
}
}
array_walk( $currentEntries, 'AWS' );
echo "Add:";
print_r($entriesToAdd);
echo "Remove:";
print_r($entriesToRemove);
This outputs:
Add:Array
(
[0] => Array
(
[id] => 100
[entry_id] => 1
)
[1] => Array
(
[id] => 102
[entry_id] => 3
)
[2] => Array
(
[id] => 103
[entry_id] => 4
)
)
Remove:Array
(
[0] => Array
(
[id] => 101
[entry_id] => 2
)
)

PHP warning array to string conversion loop inside array key

<?php $student = array(
1 => array(
"firstname" => "first",
"name" => "first",
"group" => "grp01",
"score" => array(
"ASP" => 86,
"PHP" => 79,
"JAVA" => 72,
"HTML" => 96,
"JAVASCRIPT" => 98,
"VBNET" => 66
)
),
2 => array(
"firstname" => "second",
"name" => "second",
"group" => "grp01",
"score" => array(
"ASP" => 80,
"PHP" => 70,
"JAVA" => 71,
"HTML" => 92,
"JAVASCRIPT" => 90,
"VBNET" => 78
)
),
3 => array(
"firstname" => "third",
"name" => "third",
"group" => "grp02",
"score" => array(
"ASP" => 88,
"PHP" => 88,
"JAVA" => 89,
"HTML" => 96,
"JAVASCRIPT" => 98,
"VBNET" => 71
)
) ); ?>
<?php
foreach($student as $std) {
foreach($std as $key => $p){
echo $std[$key];
} } ?>
i am trying to print in echo each student with they average score but right now i am stuck i got a warning about array to string convertion can someone give me some hint how i am suppose to do my loop.
Use PHP-functions to calculate the average for every student, rounded to two digits:
foreach($student as $std) {
$avg = round(array_sum($std['score']) / count($std['score']), 2);
echo $std['name']. ": $avg <br />";
}
see it working: http://codepad.viper-7.com/RBINCd
You are iterating the wrong array, once inside each student you must iterate over the "score", if not you were trying to convert the score array to a string:
foreach($student as $std) {
foreach($std["score"] as $language => $score) {
echo $score;
}
}
The error you are getting comes when you try to echo the "score" portion of the array. As it is itself an array it cannot be echo'd out in this way.
You will need another loop to add up the scores, then get the average outside of it.
Something along the lines of:
foreach($student as $std) {
foreach($std as $key => $p){
if ( $key === 'score'){
$avg = 0;
foreach( $p as $score){
$avg += $score;
}
$avg = ($avg/size_of($p));
}
}
}

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