[
{
"id": 1573695284631,
"name": "Cars",
"pid": 0,
"children": [
{
"id": 1573695292010,
"name": "Audi",
"pid": 1573695284631
},
{
"id": 1573695305619,
"name": "BMW",
"pid": 1573695284631,
"children": [
{
"id": 1573695328137,
"name": "3 Series",
"pid": 1573695305619
},
{
"id": 1573695335102,
"name": "X5",
"pid": 1573695305619
}
]
}
]
},
{
"id": 1573695348647,
"name": "Motorcycles",
"pid": 0,
"children": [
{
"id": 1573695355619,
"name": "Ducatti",
"pid": 1573695348647
}
]
}
]
Suppose I have this node-tree-like array in PHP (represented above in json for readability). For a given child node ID, I would like to find all parent node IDs that it's nested under. For example,
getParentNodes($haystack, $child_node_id=1573695328137); //[1573695284631, 1573695292010, 1573695305619]
I assume this is a use case for recursion. Here's my best attempt:
function getParentNodes($haystack, $child_node_id) {
if( empty($haystack->children) )
return;
foreach($haystack->children as $child) {
if($child->id == $child_node_id) {
// $child found, now recursively get parents
} else {
getParentNodes($child, $child_node_id);
}
}
}
This one will walk the tree until it hits the desired id.
In all cases where the leaf is not the desired one, it will return false - and collapse up the stack resulting in false or an array of parent-ids if the child is found.
Code
function getParentNodes($haystack, $child_node_id) {
foreach ($haystack as $element) {
if ($element['id'] === $child_node_id) {
// return [$element['id']]; // uncomment if you want to include child itself
return [];
} else if (array_key_exists('children', $element)) {
$parentNodes = getParentNodes($element['children'], $child_node_id);
if ($parentNodes !== false) {
return [$element['id'], ...$parentNodes];
}
}
}
return false;
}
Outputs parent ids:
array(2) {
[0]=>
int(1573695284631)
[1]=>
int(1573695305619)
}
Working example.
You missing return result. This is what you want.
function getParentNodes($arr, $child_node_id) {
$result = [];
foreach($arr as $item) {
if($item->pid == $child_node_id) {
$result[] = $item->id;
}
if(!empty($item->children)) {
$result[] = getParentNodes($item->children, $child_node_id);
}
}
return $result;
}
also you need get values as flat array
$values = getParentNodes($values, 1573695284631);
// do flat arr
array_walk_recursive($values,function($v) use (&$result){ $result[] = $v; });
// your values
var_dump($result);
Source reference for flat array
I ended up writing 2 recursive functions
function treeSearch($needle, $haystack) {
foreach($haystack as $node) {
if($node->id == $needle) {
return $node;
} elseif ( isset($node->children) ) {
$result = treeSearch($needle, $node->children);
if ($result !== false){
return $result;
}
}
}
return false;
}
treeSearch will find the node in the tree, then I need to recursively go up the tree until the parent id (pid) is 0
function getParents($node, $hierarchy, $all_parent_ids=[]) {
if($node->pid != 0) {
$parent_node = treeSearch($node->pid, $hierarchy);
$all_parent_ids[] = $parent_node->id;
$result = getParents($parent_node, $hierarchy, $all_parent_ids);
if ($result !== false){
return $result;
}
}
return $all_parent_ids;
}
then, supposing the tree is called $tree I can call them like:
$node = treeSearch(1573695328137, $tree);
$parents = getParents($node, $tree);
This is the best solution to take the parent of a child !
function getPathParent($id, $tree='',$opts='', &$path = array()) {
$in = array_replace(array(
'id'=>'id',
'child'=>'children',
'return'=>'id'
),(array)$opts);
if ( is_array($tree) && !empty($tree) ){
foreach ($tree as $item) {
if ($item[$in['id']] == $id) {
array_push($path, $item[$in['return']]);
return $path;
}
if ( isset($item[$in['child']]) && !empty($item[$in['child']]) ) {
array_push($path, $item[$in['return']]);
if (getPathParent($id, $item[$in['child']],$opts, $path) === false) {
array_pop($path);
} else {
return $path;
}
}
}
}
return false;
}
$tree = [
[
"id" => 1573695284631,
"name" => "Cars",
"pid" => 0,
"children" => [
[
"id" => 1573695292010,
"name" => "Audi",
"pid" => 1573695284631
],
[
"id" => 1573695305619,
"name" => "BMW",
"pid" => 1573695284631,
"children" => [
[
"id" => 1573695328137,
"name" => "3 Series",
"pid" => 1573695305619
],
[
"id" => 1573695335102,
"name" => "X5",
"pid" => 1573695305619
]
]
]
]
],
[
"id" => 1573695348647,
"name" => "Motorcycles",
"pid" => 0,
"children" => [
[
"id" => 1573695355619,
"name" => "Ducatti",
"pid" => 1573695348647
]
]
]
];
$getParentNode = getPathParent(1573695335102,$tree);
var_export($getParentNode);
// return:
/*
array (
0 => 1573695284631,
1 => 1573695305619,
2 => 1573695335102,
)
*/
$getParentNode = getPathParent(1573695335102,$tree,array('return'=>'name'));
var_export($getParentNode);
// return:
/*
array (
0 => 'Cars',
1 => 'BMW',
2 => 'X5',
)
*/
$getParentNode = getPathParent(1573695335102,$tree,array('id'=>'id','child'=>'children','return'=>'pid'));
var_export($getParentNode);
// return:
/*
array (
0 => 0,
1 => 1573695284631,
2 => 1573695305619,
)
*/
I'm creating simple PHP for output data to apexcharts javascript charts. To make apexcharts usable output I need to provide x and y value of the graphs as JSON. below code, I wrote to output the expected JSON.
$data_arr = array();
global $mysqli_conn;
$result = $mysqli_conn->query("sql");
$sql_out = array();
$sql_out = $result->fetch_all(MYSQLI_ASSOC);
$num_rows = mysqli_num_rows($result);
if ($num_rows < 1){
echo "zero";
}else{
foreach($sql_out as $item) {
$data_arr['x'][] = $item['time'];
$data_arr['y'][] = $item['status_code'];
}
}
$test_arr = array(
array(
"name"=>"lock",
"data"=>array($data_arr),
)
);
echo json_encode($test_arr);
my expected json output is like below
[
{
"name": "lock",
"data": [
{
"x": "2019-05-30 07:53:07",
"y": "1470"
},
{
"x": "2019-05-29 07:52:27",
"y": "1932"
}
]
}
]
But when I request data from my code what I'm getting something like this
[
{
"name": "lock",
"data": [
{
"x": [
"2019-05-30 07:53:07",
"2019-05-29 07:52:27",
"2019-05-26 15:46:56",
"2019-05-25 07:39:24"
],
"y": [
"1470",
"1932",
"1940",
"1470"
]
}
]
}
]
How can I create my expected JSON result from PHP code?.
You're creating them on a seprate space. When you declare and push them, put them on one container:
foreach ($sql_out as $item) {
$data_arr[] = array(
'x' => $item['time'],
'y' => $item['status_code']
);
}
When you do this:
$data_arr['x'][] = $item['time'];
$data_arr['y'][] = $item['status_code'];
They are on a separate containers, x and y containers, therefore you get the wrong format, like the one you showed.
When you declare them as:
$data_arr[] = array(
'x' => $item['time'],
'y' => $item['status_code']
);
You're basically tellin to push the whole sub batches but together.
I am using following code for making data coming from database as json format
public function employeeSearch()
{
$arrayOfEmployee = array();
$arrayToPush = array();
$arrayToJSON = array();
$new_item = $this->apicaller->sendRequest(array(
"controller" => "Employee",
"action" => "employeeSearch",
"searchCriteria" => "12345"
));
$arrayOfEmployee = json_decode($new_item,true);
foreach($arrayOfEmployee as $key => $employee)
{
$arrayToPush = array('data' => $employee['FullName'], 'value' => $employee['_id']['$oid']);
array_push($arrayToJSON, $arrayToPush);
}
echo json_encode($arrayToJSON);
}
The output is
[{"data":"Aasiya Rashid Khan","value":"5aa662b0d2ccda095400022f"},
{"data":"Sana Jeelani Khan","value":"5aa75d8fd2ccda0fa0006187"},
{"data":"Asad Hussain Khan","value":"5aaa51ead2ccda0860002692"},
{"data":"Ayesha Khan Khann","value":"5aab61b4d2ccda0bc400190f"},
{"data":"adhar card name","value":"5aaba0e1d2ccda0bc4001910"}
]
Now I want that json elements should look like
{
"suggestions": [
{
"value": "Guilherand-Granges",
"data": "750"
},
{
"value": "Paris 01",
"data": "750"
}
]
}
I have to implement this in jQuery autocomplete plugin...
Please help!!!
Replace the last line with
echo json_encode(["suggestions" => $arrayToJSON]);
This should result in the wanted result!
(This hold only true if you igonre the fact that the data in value and name is not the same/similar)
I have this following result in my query:
I'm trying to create an array like this in php:
[
{
"software_version": "1.0",
"version_date": "10/08/2016",
"changelog": [
{
"type": "IMP",
"description": "Initial version."
}
]
},
{
"software_version": "1.0.1",
"version_date": "27/07/2017",
"changelog": [
{
"type": "ADD",
"description": "HostPanel update manager."
},
{
"type": "ADD",
"description": "Hook OnDaemonMinute."
}
]
}
]
I need to combine the result with the software_version row.
Any help is appreciated.
My php code:
$changelog = array();
foreach ($result as $r) {
$changelog[] = array(
'software_version' => $r['software_version'],
'version_date' => $r['version_date'],
'changelog' => array(
array(
'type' => 'IMP', // help
'description' => 'Initial version.'
)
)
);
}
The key is to use the software version as a key in $changelog as you build it.
$changelog = array();
foreach ($result as $r) {
// get the version (just to make the following code more readable)
$v = $r['software_version'];
// create the initial entry for the version if it doesn't exist yet
if (!isset($changelog[$v]) {
$changelog[$v] = ['software_version' => $v, 'version_date' => $r['version_date']];
}
// create an entry for the type/description pair
$change = ['type' => $r['type'], 'description' => $r['description']];
// add it to the changelog for that version
$changelog[$v]['changelog'][] = $change;
}
You'll need to use array_values to reindex $changelog before JSON encoding it in order to produce the JSON array output you're going for.
$changelog = array_values($changelog);
I have a multi- and variable-level json file that looks like the example at the bottom of this post. What I need to do is search for a particular value, let's say "Gap junction" and return the value for "name" for all of the higher level parents, in this example "Junction", "Plasma membrane" and "Cell". I need to do this using php and I think I need a recursive loop to traverse the array that will record the "name" value for each depth level into an array and then return this "name" array once the search term is found, but I'm struggling a bit at achieving this. Any help would be appreciated.
{
"name": "Cell",
"children": [
{
"name": "Plasma membrane",
"children": [
{
"name": "Junction",
"children": [
{"name": "Adherens junction"},
{"name": "Caveola"},
{"name": "Gap junction"},
{"name": "Lipid raft"},
{"name": "Tight junction"}
]
},
{"name": "Focal adhesion"}
]
},
{
"name": "Vesicle",
"children": [
{
"name": "Endosome",
"children": [
{"name": "Early Endosome"},
{"name": "Late Endosome"},
{"name": "Recyling Endosome"}
]
},
{ "name": "Microsome"}
]
}
]
}
EDIT
Current code as requested. The $found variable is certainly not working how I intended it too. Code is based/modified on this answer: Get Parent and Child depth level from JSON using PHP?
$jsonString = file_get_contents("./information/localization.json");
$jsonArray = json_decode($jsonString);
$currOrganelle = "Gap junction";
$parents = read_tree_recursively($jsonArray, $currOrganelle);
function read_tree_recursively($items, $searchTerm, $result = array(), $level = 0, $found = false) {
foreach($items as $child) {
if(!$found) {
$currName = $child->name;
if($currName == $searchTerm) {
$found = true;
return $result;
}
elseif(!empty($child->children)) {
$result[$level] = $currName;
$result = read_tree_recursively($child->children, $searchTerm, $result, $level + 1, $found);
if($found) return $result;
}
else {
}
}
else {
return $result;
}
}
}
Solution with RecursiveIteratorIterator and RecursiveArrayIterator classes:
// $str - is your initial json string
$decoded = json_decode($str, TRUE);
function getParentNameKeys($arr = [], $needle = "") {
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($arr));
$nameKeys = [];
foreach ($iterator as $key => $value) {
if ($value === $needle) {
$depth = $iterator->getDepth();
while ($depth--){
if ($iterator->getSubIterator($depth)->offsetExists('name')) {
$nameKeys[] = $iterator->getSubIterator($depth)->offsetGet('name');
}
}
}
}
return $nameKeys;
}
$nameKeys = getParentNameKeys($decoded, "Gap junction");
var_dump($nameKeys);
// the output:
array (size=3)
0 => string 'Junction' (length=8)
1 => string 'Plasma membrane' (length=15)
2 => string 'Cell' (length=4)
$nameKeys = getParentNameKeys($decoded, "Early Endosome");
var_dump($nameKeys);
// the output:
array (size=3)
0 => string 'Endosome' (length=8)
1 => string 'Vesicle' (length=7)
2 => string 'Cell' (length=4)
http://php.net/manual/en/class.recursiveiteratoriterator.php