I have some data on a MySQL database representing a tree structure, and I want to convert it into JSON. I have used a recursive function to read all the data but I have no idea on how to convert into an array.
Here is the recursive function:
public function buildTree($parent, $level) {
// retrieve all children of $parent
$results = Department::all()->where('parent_id',$parent);
// display each child
foreach($results as $result)
{
echo $this->buildTree($result['id'], $level+1);
}
}
And the following is the JSON result I'd like to have in the end:
[
{
"id":1,
"text":"Root node",
"children":[
{
"id":2,
"text":"Child node 1",
"children":[
{
"id":4,
"text":"hello world",
"children":[{"id":5,"text":"hello world2"}]
}
]
},
{
"id":3,
"text":"Child node 2"
}
]
}
]
Here is the sample data
public function buildTree($parent, $level) {
// The array which will be converted to JSON at the end.
$json_return = array();
// Get the current element's data.
$results = Department::all()->where('id',$parent);
$json_return['id'] = $parent;
$json_return['text'] = $results[0]['text']; // Or however you access the "text" parameter of the end JSON from the database.
// Retrieve all children of $parent
$results = Department::all()->where('parent_id',$parent);
if (count($results) > 0)
{
$json_return['children'] = array();
foreach($results as $result)
{
$json_return['children'][] = $this->buildTree($result['id'], $level+1);
}
}
// Going to assume that $level by default is 0
if ($level == 0)
{
echo json_encode(array($json_return));
}
return $json_return;
}
Related
i'm having some troubles creating a multidimentional JSON object in PHP.
My Postgresql database looks like this:
Id Name Parent
1 Active NULL
2 Passive NULL
3 Fixed 1
4 Dynamic 3
5 Taxes 2
6 Fair 2
...
The parent column is linked with the Id in the first column
What i want to accomplish is this:
[
{
"name": "Active",
"children": [
{
"name": "Fixed",
"children": [
{
"name": "Dynamic",
"children": NULL
}
]
}
]
},
{
"name": "Passive",
"children": [
{
"name": "Taxes",
"children": NULL
},
{
"name": "Fair",
"children": NULL
}
]
}
]
So first of all i FETCH the data out of our database with
$result = fetchAll(PDO::FETCH_OBJ); // fetches every row in an object
i could send this result to the frontend (javascript) and convert this data to JSON there but then i send the column names with it and i don't think that is a good idea in security terms.
First of all i want to make the top level of the JSON file. With the help of this topic Object to array in PHP i manage to put that together:
$mainArray = [];
foreach ($result as $value) {
if ($value['Parent'] === NULL) {
$object = new stdClass();
$object->name = $value['Name'];
$object->children = [];
$mainArray[] = $object;
}
}
This is my result:
[
{
name: "Actief",
children: [ ]
},
{
name: "Passief",
children: [ ]
}
]
But i'm stuck adding children to the correct parent. I just can't seem to find how to do it.
I need to do something like this:
Add Fixed to Object where Object->Name is 1 = Active.
This will do the job. Assuming your child data won't come before your parent data.
$mainArray = [];
foreach ($result as $key=>$value) {
if ($value['Parent'] === NULL) {
$object = new stdClass();
$object->name = $value['Name'];
$mainArray[$value['Id']] = $object;
}else{
$childOBJ = new stdClass();
$childOBJ->name = $value['Name'];
$mainArray[$value['Parent']]->children[] = $childOBJ;
}
}
$finalArray = array_values($mainArray); // changes to indexed array for json purpose
UPDATE: WITH RECURSION and refrence
function makeTree($result, $parentId=NULL){
$tree = [];
foreach ($result as $value) {
if($value['Parent'] == $parentId){
$object = new stdClass();
$object->name = $value['Name'];
$child = makeTree($result, $value['Id']);
if($child){
$object->children=$child;
}
$tree[] = $object;
}
}
return $tree;
}
$finalArray = makeTree($result);
I'm trying to generate a JSON string that includes the id and url for all my categories, subcategories, and sub-subcategories. The code below only gets me as far as the top-level category, but I also need the second and third as well. My goal is to create a dynamically updating sitemap that decodes the string and makes an unordered list of every category level.
public function createCategoryTree() {
$_categories = Mage::getModel('catalog/category')->getCollection()->addAttributeToSelect('*')->addIsActiveFilter()->addLevelFilter(2)->addOrderField('position'); // load all categories
$arr = array();
if ($_categories){ // if there are categories
foreach ($_categories as $cat){
$cat_name = $cat->getName(); // name as key
if (strlen(stristr($cat_name,'default')) < 3) {
$cat_id = $cat->getId(); // id
$cat_url = $cat->getUrl(); // url
$arr[$cat_id] = array('title'=>$cat_name,'url'=>$cat_url);
}
}
}
print_r (json_encode($arr));
die;
}
I get something like this:
{
"637": {
"title": "bikes",
"url": "http:www.123.com/shop/bicycles "
}
}
But I want something like this:
{
"637": {
"title": "bikes",
"url": "http:www.123.com/shop/bicycles",
"children": {
"658": {
"title":"wheels",
"url":"http:www.123.com/shop/bicycles/wheels"
},
"489": {
"title": "pumps",
"url":"http:www.123.com/shop/bicycles/pumps"
}
}
}
Appreciate your time and help!
You can use some functionality provided by Mage_Catalog_Model_Resource_Category_Tree for this. See if this script works for you:
<?php
require_once('../app/Mage.php');
Mage::app();
function getCategoryTree($recursionLevel, $storeId = 1)
{
$parent = Mage::app()->getStore()->getRootCategoryId();
$tree = Mage::getResourceModel('catalog/category_tree');
/* #var $tree Mage_Catalog_Model_Resource_Category_Tree */
$nodes = $tree->loadNode($parent)
->loadChildren($recursionLevel)
->getChildren();
$tree->addCollectionData(null, false, $parent);
$categoryTreeData = array();
foreach ($nodes as $node) {
$categoryTreeData[$node->getData('entity_id')] = getNodeChildrenData($node);
}
return $categoryTreeData;
}
function getNodeChildrenData(Varien_Data_Tree_Node $node)
{
$data = array(
'title' => $node->getData('name'),
'url' => $node->getData('url_key'),
);
foreach ($node->getChildren() as $childNode) {
if (!array_key_exists('children', $data)) {
$data['children'] = array();
}
$data['children'][$childNode->getData('entity_id')] = getNodeChildrenData($childNode);
}
return $data;
}
print_r(json_encode(getCategoryTree(3)));
I have this
{
"items":[
{
"id":463282624,
"original_id":463282624,
"defindex":10175,
"level":1,
"quality":4,
"inventory":2147483980,
"quantity":1,
"attributes":[
{
"defindex":187,
"value":1106771968,
"float_value":31
}
]
},
{
"id":465686099,
"original_id":465686099,
"defindex":10175,
"level":1,
"quality":4,
"inventory":2147483979,
"quantity":1,
"attributes":[
{
"defindex":187,
"value":1106771968,
"float_value":31
}
]
}
]
}
How can i take out the ['id'] of the item with ['defindex'] = 10175
Please help!
PHP doesn't provide any way to retrieve elements by the contents, so you have to write a loop:
foreach ($object['items'] as $item) {
if ($item['defindex'] == 10175) {
$id = $item['id'];
break;
}
}
If you're going to need to do this repeatedly, you should transform your data into an associative array that uses defindex as the key, then you can access them easily.
$items_by_defindex = array();
foreach ($object['items'] as $item) {
$items_by_defindex[$item['defindex']] = $item;
}
$id = $items_by_defindex[10175];
I have a json feed that is more or less a list of objects
each has it's own id and idParent. objects that have idParent of null are the base parent elements. What I'm trying to achieve is to make a proper multidimensional array like a tree view. Keep in mind that children can have children too.
{
"obj1":{
"idParent":null,
"id":"parent1"
},
"obj2":{
"idParent":null,
"id":"parent2"
},
"obj3":{
"idParent":null,
"id":"parent3"
},
"obj4":{
"idParent":null,
"id":"parent4"
},
"obj5":{
"idParent":null,
"id":"parent5"
},
"obj6":{
"idParent":"parent1",
"id":"layer1-1"
},
"obj7":{
"idParent":"parent1",
"id":"layer1-2"
},
"obj8":{
"idParent":"parent2",
"id":"layer1-3"
},
"obj9":{
"idParent":"parent4",
"id":"layer1-4"
},
"obj10":{
"idParent":"parent3",
"id":"layer1-5"
},
"obj11":{
"idParent":"layer1-1",
"id":"layer2-1"
},
"obj12":{
"idParent":"parent5",
"id":"layer2-2"
},
"obj13":{
"idParent":"layer1-4",
"id":"layer2-3"
},
"obj14":{
"idParent":"layer1-5",
"id":"layer2-4"
},
"obj15":{
"idParent":"layer1-5",
"id":"layer2-5"
}
}
I've managed to filter out the root parents but after that I fail very bad
The first function does filter out the root parent nodes with idParent of null.
function decodeData($data) {
global $out;
foreach ($data as $key => $obj) {
if (is_array($obj)) {
foreach ($obj as $prop => $value) {
if ($prop == 'idParent') {
if($value == null) {
array_push($out, $obj);
unset($data[$key]);
}
}
}
}
}
if (count($data) > 0) {
decodeData($data);
} else {
echo json_encode(array('length'=>count($data)));
}
}
And this is what I'm experimenting on with no result
function decodeData($arrays) {
global $out;
foreach ($arrays as $array_name => $arr) {
foreach ($arr as $arr_prop => $arr_val) {
if ($arr_prop == 'idParent' && $arr_val == null) { // we found root parents
array_push($out, $arr);
unset($arrays[$array_name]); //remove array from the list
} else { // check if idParent is inside out
foreach ($out as $out_arr_name => $out_arr) { // iterate through out arrays
foreach ($out_arr as $out_arr_prop => $out_prop_val) { //
if ($out_arr_prop == 'id' && $arr_prop == 'idParent' && $out_arr_val == $arr_val) {
array_push($out_arr['children'], $obj);
unset($arrays[$array_name]);
}
}
}
}
}
}
if (count($arrays) > 0) {
decodeData($arrays);
} else {
echo json_encode(array('length'=>count($arrays)));
}
}
If anyone could provide some help I would really appreciate it.
I couldn't figure out what output do you want, so I just made a simple tree structure:
$data = json_decode( $your_json_string );
// Store each element in a lookup table indexed by element id
// 0th pass: put a fake root element there
$by_id = array(
'*' => new stdclass
);
// First pass: put each element into there
foreach( $data as $o ) $by_id[ $o->id ] = $o;
// Second pass: add each element into its parent's children array
foreach( $data as $o ){
$pid = $o->idParent ? $o->idParent : '*';
$p = $by_id[ $pid ];
$p->children[] = $o;
}
// Trash everything else, we start from the (fake) root element:
$tree = $by_id['*']->children;
/**** REVERSE ****/
$todo = $tree;
$json = array();
while( $todo ){
$o = array_shift( $todo );
if( isset( $o->children )){
$todo = array_merge( $todo, $o->children );
unset( $o->children );
}
$json[] = $o;
};
echo json_encode( $json );
The result:
http://codepad.viper-7.com/V7PjDh
I have a multidimensional PHP array looking like this in JSON:
array = [{
"id":"1",
"key":"Ferrari",
"type":"car"},
{
"id":"1",
"key":"Red",
"type":"color"},
{
"id":"73",
"key":"Yellow",
"type":"color"
}]
Because it's actually a search result, I would like to, dynamically combine the results where the id's are the same. In other words the new array should look like:
array = [{
"id":"1",
"key":"Red Ferrari",
"type":"keyword"},
{
"id":"73",
"key":"Yellow",
"type":"color"
}]
I have been looking at a lot of PHP functions, but they have a limited functionality, in multidimensional arrays. Any suggestions are appreciated :)
Many Regards
Andreas
There's no base functions to do as specific thing as you mention. So you can make something like this:
print_r(my_array_merge($data));
function my_array_merge($data)
{
// sort all records by id to merge them later
$data_by_id = array();
foreach ($data as $item)
{
if (!isset($data_by_id[ $item['id'] ])) {
$data_by_id[ $item['id'] ] = array();
}
$data_by_id[ $item['id'] ][] = $item;
}
// merge records with same id
$return = array();
foreach ($data_by_id as $id => $items)
{
foreach ($items as $item)
{
if (!isset($return[ $id ])) {
$return[ $id ] = $item;
} else {
$return[ $id ]['key'] .= ' ' . $item['key'];
$return[ $id ]['type'] = 'keyword'; // I don't really get what you mean by 'keyword'
}
}
}
// reset keys before return
return array_values($return);
}