MYSQL database to JSON format using PHP - php

I tried to convert get data from mysql in json format. For that I am using PHP.
My PHP code is
<?php
define('_HOST_NAME', 'localhost');
define('_DATABASE_USER_NAME', 'root');
define('_DATABASE_PASSWORD', 'admin321');
define('_DATABASE_NAME', 'tree');
$dbConnection = new mysqli(_HOST_NAME,
_DATABASE_USER_NAME, _DATABASE_PASSWORD, _DATABASE_NAME);
if ($dbConnection->connect_error) {
trigger_error('Connection
Failed: ' . $dbConnection->connect_error, E_USER_ERROR);
}
$_GLOBAL['dbConnection'] = $dbConnection;
$categoryList = categoryParentChildTree();
foreach($categoryList as $key => $value){
echo $value['name'].'<br>';
}
function categoryParentChildTree($parent = 0,
$spacing = '', $category_tree_array = '') {
global $dbConnection;
$parent = $dbConnection->real_escape_string($parent);
if (!is_array($category_tree_array))
$category_tree_array = array();
$sqlCategory = "SELECT id,name,parent FROM php WHERE parent = $parent ORDER BY id ASC";
$resCategory=$dbConnection->query($sqlCategory);
if ($resCategory->num_rows != null && $resCategory->num_rows>0) {
while($rowCategories = $resCategory->fetch_assoc()) {
$category_tree_array[] = array("id" => $rowCategories['id'], "name" => $spacing . $rowCategories['name']);
$category_tree_array = categoryParentChildTree(
$rowCategories['id'],
' '.$spacing . '- ',
$category_tree_array
);
}
}
return $category_tree_array;
}
?>
mysql table
ID PARENT NAME
1 0 category
2 1 fruit
3 2 apple
4 2 orange
5 1 animals
6 5 tiger
7 5 lion
8 1 car
My output is:
category
- fruit
- - apple
- - orange
- animal
- - tiger
- - lion
- cars
I want to get nested json output. Already asked here. No proper response.
I tried with json_encode, not getting nested json.
UPDATED PHP
<?php
$con=mysqli_connect("localhost","root","admin321","tree");
if (mysqli_connect_errno()) //con error
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$r = mysqli_query($con,"SELECT * FROM php ");
$data = array();
while($row = mysqli_fetch_assoc($r)) {
$data[] = $row;
}
function buildtree($src_arr, $parent_id = 0, $tree = array())
{
foreach($src_arr as $idx => $row)
{
if($row['parent'] == $parent_id)
{
foreach($row as $k => $v)
$tree[$row['id']][$k] = $v;
unset($src_arr[$idx]);
$tree[$row['id']]['children'] = buildtree($src_arr, $row['id']);
}
}
ksort($tree);
return $tree;
}
function insertIntoNestedArray(&$array, $searchItem){
// Insert root element
if($searchItem['parent'] == 0){
array_push($array, $searchItem);
return;
}
if(empty($array)){ return; }
array_walk($array, function(&$item, $key, $searchItem){
if($item['id'] == $searchItem['parent']){
array_push($item['children'], $searchItem);
return;
}
insertIntoNestedArray($item['children'], $searchItem);
}, $searchItem);
}
$nestedArray = array();
foreach($data as $itemData){
// First: Mount the nested array item
$nestedArrayItem['id'] = $itemData['id'];
$nestedArrayItem['name'] = $itemData['name'];
$nestedArrayItem['parent'] = $itemData['parent'];
$nestedArrayItem['children'] = array();
// Second: insert the item into the nested array
insertIntoNestedArray($nestedArray, $nestedArrayItem);
}
$json = json_encode($nestedArray);
echo $json;
?>

Simply this: json_encode($output , JSON_FORCE_OBJECT);

Your Nested Output is just an human-representation of the stored data you have in your database. Its a human thing. Machines can't understand that, that's why in mysql you need a column to tell the category parent.
So, your problem is that you're trying to convert to JSON your already manipulated data. You need to convert to JSON your raw data, and then manipulate it in the code that receives the JSON.
use json_encode to encode the raw data:
$raw_data = $resCategory->fetch_all();
return json_encode($raw_data);
Also, just a note: this $_GLOBAL variable you're using... you're not trying to refer to the internal php $GLOBALS superglobal, you are?
EDIT:
Ok, now that you explained that you need the nested json format, you will need to use some recursion to build an nested array of arrays and then use the json_encode on it.
First: Get the raw data:
$resCategory=$dbConnection->query($sqlCategory);
$raw_data = $resCategory->fetch_all();
Now, suppose this $raw_data variable returns an array like this:
array (
0 => array (
'ID' => 1,
'PARENT' => 0,
'NAME' => 'category',
),
1 => array (
'ID' => 2,
'PARENT' => 1,
'NAME' => 'fruit',
),
2 => array (
'ID' => 3,
'PARENT' => 2,
'NAME' => 'apple',
),
3 => array (
'ID' => 4,
'PARENT' => 2,
'NAME' => 'orange',
),
4 => array (
'ID' => 5,
'PARENT' => 1,
'NAME' => 'animals',
),
5 => array (
'ID' => 6,
'PARENT' => 5,
'NAME' => 'tiger',
),
6 => array (
'ID' => 7,
'PARENT' => 5,
'NAME' => 'lion',
),
7 => array (
'ID' => 8,
'PARENT' => 1,
'NAME' => 'car',
)
)
Second: Build up an recursive function to insert items of this array into another array, the $nestedArray (that we will create in the third step).
function insertIntoNestedArray(&$array, $searchItem){
// Insert root element
if($searchItem['parent'] == 0){
array_push($array, $searchItem);
return;
}
// Stop the recursion when the array to check is empty
if(empty($array)){ return; }
// Walk the array searching for the parent of the search item
array_walk($array, function(&$item, $key, $searchItem){
// If the parent is found, then append the search item to it
if($item['id'] == $searchItem['parent']){
array_push($item['children'], $searchItem);
return;
}
// If the parent wasn't found, walk thought the children of the array
insertIntoNestedArray($item['children'], $searchItem);
}, $searchItem);
}
Third: Create the $nestedArray and populate it by loop through the $raw_data array and calling the recursive function:
$nestedArray = array();
foreach($data as $itemData){
// First: Mount the nested array item
$nestedArrayItem['id'] = $itemData['ID'];
$nestedArrayItem['name'] = $itemData['NAME'];
$nestedArrayItem['parent'] = $itemData['PARENT'];
$nestedArrayItem['children'] = array();
// Second: insert the item into the nested array
insertIntoNestedArray($nestedArray, $nestedArrayItem);
}
Fourth: Now its just to json_encode the $nestedArray:
$json = json_encode($nestedArray);
You can do an echo $json and the result will be:
[{"id":1,"name":"category","parent":0,"children":[{"id":2,"name":"fruit","parent":1,"children":[{"id":3,"name":"apple","parent":2,"children":[]},{"id":4,"name":"orange","parent":2,"children":[]}]},{"id":5,"name":"animals","parent":1,"children":[{"id":6,"name":"tiger","parent":5,"children":[]},{"id":7,"name":"lion","parent":5,"children":[]}]},{"id":8,"name":"car","parent":1,"children":[]}]}]

Related

Aggregate arrays in multilevel array if their values match

I have an array in the following format:
array(5){
[0] =>
array(4){
['product-id'] => 8931
['product'] => 'Cake'
['description'] => 'Yellow cake'
['quantity'] => 1
}
[1] =>
array(4){
['product-id'] => 8921
['product'] => 'Cookies'
['description'] => 'Chocolate chip cookies'
['quantity'] => 2
}
[2] =>
array(4){
['product-id'] => 8931
['product'] => 'Cake'
['description'] => 'Yellow cake'
['quantity'] => 1
}
[3] =>
array(4){
['product-id'] => 8931
['product'] => 'Cake'
['description'] => 'Yellow cake'
['quantity'] => 4
}
[4] =>
array(4){
['product-id'] => 8933
['product'] => 'Cake'
['description'] => 'Chocolate cake'
['quantity'] => 1
}
}
How can I compare all the arrays to each other?
In my code I have sorted all the arrays by product ID, and written a for to compare two rows at a time, but now I see why that won't work.
function cmp($a, $b){
return strcmp($a[0], $b[0]);
}
function combineArrays($arrays){
usort($arrays, "cmp");
for($i = 1; $i < count($arrays); $i++){
$f_row = $arrays[$i];
$next = $i + 1;
$s_row = $arrays[$next];
if($f_row[0] == $s_row[0]){
if($f_row[1] == $s_row[1]){
if($f_row[2] == $s_row[2]){
$q1 = (int) $f_row[3];
$q2 = (int) $s_row[3];
$total = $q1 + $q2;
unset($f_row[3]);
$f_row[5] = $total;
unset($arrays[$next]);
}
}
}
}
return $arrays;
}
What is a better way to do this?
For example, to take the first array and compare it to the next, value for value. As soon as one of the first 3 values doesn't match, you go on to compare that row to the next one. If all of the first three values match, add up the quantity value of the two arrays, assign that to the first array's quantity, and get rid of the second array. There could be more matches, so continue comparing that array until you have gone through the whole list.
My favorite solution uses array_reduce():
$filtered = array_reduce(
// Reduce the original list
$arrays,
// The callback function adds $item to $carry (the partial result)
function (array $carry, array $item) {
// Generate a key that contains the first 3 properties
$key = $item['product-id'].'|'.$item['product'].'|'.$item['description'];
// Search into the partial list generated until now
if (array_key_exists($key, $carry)) {
// Update the existing item
$carry[$key]['quantity'] += $item['quantity'];
} else {
// Add the new item
$carry[$key] = $item;
}
// The array_reduce() callback must return the updated $carry
return $carry;
},
// Start with an empty list
array()
);
try this
$arr=array(
array(
'product-id' => 8931,
'product' => 'Cake',
'description' => 'Yellow cake',
'quantity' => 3,
),
array(
'product-id' => 8921,
'product' => 'Cookies',
'description' => 'Chocolate chip cookies',
'quantity' => 2,
),
array(
'product-id' => 8931,
'product' => 'Cake',
'description' => 'Yellow cake',
'quantity' => 1,
)
);
$id = array();
foreach ($arr as $key => $row)
{
$id[$key] = $row['product-id'];
}
array_multisort($id, SORT_DESC, $arr);
$result = array();
foreach ($arr as $key => $row)
{
$pid = $row['product-id'];
if(!isset($result[$pid]))
{
$result[$pid]=$row;
}else{
$result[$pid]['quantity']+=$row['quantity'];
}
}
print_r($result);
You are doing it the hard way, why not do it like this:
function combineProducts($products) {
$result = array();
foreach ($products as $product) {
//if you can have different product or descriptions
//per product id you can change this this to
//$productId = implode('|', array($product['product-id'], $product['product'], $product['description']);
$productId = $product['product-id'];
//check if we already have this product
if (isset($result[$productId])) {
//add to the quantity
$result[$productId]['quantity']+= $product['quantity'];
} else {
$result[$productId] = $product;
}
}
//sort the results (remove if not needed)
ksort($result);
//return values (change to return $result; if you want an assoc array)
return array_values($result);
}

Flatten multidimensional array to 3 levels preserving the first level keys

I have a nested multidimensional array like this:
$array = [
1 => [
[
['catName' => 'Villes', 'catUrl' => 'villes', 'parent' => 151],
[
['catName' => 'Administratif', 'catUrl' => 'territoire', 'parent' => 37],
[
['catName' => 'Gegraphie', 'catUrl' => 'geographie', 'parent' => 0]
]
]
]
]
];
I would like to flatten it to a simpler structure, like this:
array (
1 =>
array (
0 =>
array (
'catName' => 'Villes',
'catUrl' => 'villes',
'parent' => 151,
),
1 =>
array (
'catName' => 'Administratif',
'catUrl' => 'territoire',
'parent' => 37,
),
2 =>
array (
'catName' => 'Gegraphie',
'catUrl' => 'geographie',
'parent' => 0,
),
),
)
I suppose it would work with some recursive function, but my skills in there are not my best. How can I accomplish this?
Here is one way to do it. This function will collapse each level:
function collapse($array) {
// End of recursion is indicated when the first element is not an array.
if (!is_array(reset($array))) {
return array($array);
}
// Otherwise, collapse it.
return array_reduce($array, function($carry, $item) {
// Recursively collapse each item and merge them together.
return array_merge($carry, collapse($item));
}, array());
}
It can be applied to your array like this:
$collapsed = array_map("collapse", $array);
It's not pretty, but it works:
$deeparray = array(); // the really nested array goes here
$flattened = array();
function flatten($item,$key)
{
global $flattened;
if ( $key == 'catName' || $key == 'catUrl' || $key == 'parent' )
{
if ( sizeof( $flattened) == 0 )
{ $flattened[] = array( $key=>$item ); }
else
{
$last = array_pop($flattened);
if ( array_key_exists($key,$last) )
{
$flattened[] = $last;
$flattened[] = array( $key=>$item );
}
else
{
$last[ $key ] = $item;
$flattened[] = $last;
}
}
}
}
array_walk_recursive($deeparray,'flatten',$flattened);
$flattened = array($flattened);
Make a recursive call on each first level element.
Within the recursive function, first isolate the non-iterable elements and push them as a single new row into the desired result array. Then execute the recursive function on each iterable element on that level.
It is important to "pass data back up" with each each recursive call so that all deep data can be collected and returned in the top-level/finished array.
The global-level foreach modifies by reference so that the assignment of $parent mutates the original input array.
Code: (Demo)
function flattenRows($array) {
$result = [];
$scalars = array_filter($array, 'is_scalar');
if ($scalars) {
$result[] = $scalars;
}
foreach (array_diff_key($array, $scalars) as $item) {
$result = array_merge($result, flattenRows($item));
}
return $result;
}
$result = [];
foreach ($array as &$parent) {
$parent = flattenRows($parent);
}
var_export($array);
You could try
foreach($toplevel as $a){
$finalarray = $a[0];
}
if the structure will always be the same as what you've shown then i think you can do this:
$newarray[1][0] = $oldarray[1][0][0];
$newarray[1][1] = $oldarray[1][0][1][0];
$newarray[1][2] = $oldarray[1][0][1][1][0];

How to compare 2 array with same key but different value PHP

I want to ask about compare 2 arrays with same key but different value.
I have 1 array master (arrayMaster) and 2 or more array data (arrayData1, arrayData2, and maybe could be more). These array data key will have exactly one of arrayMaster data key (I've done for this thing). For data example that I get:
arrayMaster = Array( [apple] => 1 [banana] => 2 [choco] => 1 [donut] => 2 [egg] => 1 )
arrayData1 = Array( [apple] => 8 [banana] => 2 [choco] => 1 )
arrayData2 = Array( [donut] => 5 [choco] => 2 [egg] => 3 )
(We can see that arrayData1 and arrayData2 contain a key from arrayMaster key.)
These arrays I want to compare and give a calculating method. If the array key at arrayData(n) found at arrayMaster, it will do a calculating data, let said it will sum each other.
So, the result is:
arrayResult1 = 1+8 (apple have 1 from master, apple have 8 from arrayData1), 2+2, 1+1
arrayResult2 = 2+5 (donut have 2 from master, donut have 5 from arrayData2), 1+2, 1+3
So I will have 2 new array (or more, depend on how much arrayData) that contain:
arrayResult1 = ([apple] => 9 [banana] => 4 [choco] => 2);
arrayResult2 = ([donut] => 7 [choco] => 3, [egg] => 4);
Anyone know how to do this? I’”ve tried array_intersect but it didn’t work.
Do something like this:
function doCalc($master, $slave) {
$results = array();
foreach( $slave as $key => $value ) {
if( !isset($master[$key]) ) {
$results[$key] = $value;
}
else {
$results[$key] = $master[$key] + $value;
}
}
return $results;
}
$arrayResult1 = doCalc($arrayMaster, $arrayData1);
$arrayResult2 = doCalc($arrayMaster, $arrayData2);
You can write something simpler like this..
function modifyArr(&$arr,$basearray) //<=-- See I am passing & (reference) so your original array will be modified
{
foreach($arr as $k=>$v)
{
if(array_search($k,$basearray)!==null)
{
$arr[$k]=$basearray[$k]+$arr[$k];
}
}
}
modifyArr($arrayData1,$arrayMaster); //<=-- Pass your 1st array
modifyArr($arrayData2,$arrayMaster); //<=-- Pass your 2nd array
Demonstration
Using these as examples:
arrayResult1 = 1+8 (apple have 1 from master, apple have 8 from arrayData1), 2+2, 1+1
arrayResult2 = 2+5 (donut have 2 from master, donut have 5 from arrayData2), 1+2, 1+3
Why not just do this:
// The main arrays for master & data values.
$arrayMaster = array('apple' => 1, 'banana' => 2, 'choco' => 1, 'donut' => 2, 'egg' => 1);
$arrayData1 = array('apple' => 8, 'banana' => 2, 'choco' => 1);
$arrayData2 = array('donut' => 5, 'choco' => 2, 'egg' => 3);
// Set a values to check array.
$values_to_check = array('apple', 'donut');
// Init the results array.
$results_array = array();
// Roll through the values to check.
foreach ($values_to_check as $value) {
// Check if the array key exists in '$arrayMaster'.
if (array_key_exists($value, $arrayMaster)) {
// If it exists, add it to the '$results_array'.
$results_array[$value][] = $arrayMaster[$value];
// Check if the array key exists in '$arrayData1'.
if (array_key_exists($value, $arrayData1)) {
// If it exists, add it to the '$results_array'.
$results_array[$value][] = $arrayData1[$value];
}
// Check if the array key exists in '$arrayData2'.
if (array_key_exists($value, $arrayData2)) {
// If it exists, add it to the '$results_array'.
$results_array[$value][] = $arrayData2[$value];
}
}
}
// Roll through the results array and use 'array_sum' to get a sum of values.
foreach ($results_array as $results_key => $results_value) {
echo $results_key . ' : ' . array_sum($results_value) . '<br />';
}
But looking at your example, I am unclear on why you have separate arrays for $arrayData1 and $arrayData2 so here is the same code, but refactored to have nested arrays in $arrayData which should be more efficient:
// The main arrays for master & data values.
$arrayMaster = array('apple' => 1, 'banana' => 2, 'choco' => 1, 'donut' => 2, 'egg' => 1);
$arrayData = array();
$arrayData[] = array('apple' => 8, 'banana' => 2, 'choco' => 1);
$arrayData[] = array('donut' => 5, 'choco' => 2, 'egg' => 3);
// Set a values to check array.
$values_to_check = array('apple', 'donut');
// Init the results array.
$results_array = array();
// Roll through the values to check.
foreach ($values_to_check as $value) {
// Check if the array key exists in '$arrayMaster'.
if (array_key_exists($value, $arrayMaster)) {
// If it exists, add it to the '$results_array'.
$results_array[$value][] = $arrayMaster[$value];
// Roll through the values to check.
foreach ($arrayData as $arrayData_value) {
// Check if the array key exists in '$arrayData1'.
if (array_key_exists($value, $arrayData_value)) {
// If it exists, add it to the '$results_array'.
$results_array[$value][] = $arrayData_value[$value];
}
}
}
}
// Roll through the results array and use 'array_sum' to get a sum of values.
foreach ($results_array as $results_key => $results_value) {
echo $results_key . ' : ' . array_sum($results_value) . '<br />';
}

PHP foreach with Nested Array?

I have a nested array in which I want to display a subset of results. For example, on the array below I want to loop through all the values in nested array[1].
Array
(
[0] => Array
(
[0] => one
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
[1] => Array
(
[0] => two
[1] => Array
(
[0] => 4
[1] => 5
[2] => 6
)
)
[2] => Array
(
[0] => three
[1] => Array
(
[0] => 7
[1] => 8
[2] => 9
)
)
)
I was trying to use the foreach function but I cannot seem to get this to work. This was my original syntax (though I realise it is wrong).
$tmpArray = array(array("one",array(1,2,3)),array("two",array(4,5,6)),array("three",array(7,8,9)));
foreach ($tmpArray[1] as $value) {
echo $value;
}
I was trying to avoid a variable compare on whether the key is the same as the key I want to search, i.e.
foreach ($tmpArray as $key => $value) {
if ($key == 1) {
echo $value;
}
}
Any ideas?
If you know the number of levels in nested arrays you can simply do nested loops. Like so:
// Scan through outer loop
foreach ($tmpArray as $innerArray) {
// Check type
if (is_array($innerArray)){
// Scan through inner loop
foreach ($innerArray as $value) {
echo $value;
}
}else{
// one, two, three
echo $innerArray;
}
}
if you do not know the depth of array you need to use recursion. See example below:
// Multi-dementional Source Array
$tmpArray = array(
array("one", array(1, 2, 3)),
array("two", array(4, 5, 6)),
array("three", array(
7,
8,
array("four", 9, 10)
))
);
// Output array
displayArrayRecursively($tmpArray);
/**
* Recursive function to display members of array with indentation
*
* #param array $arr Array to process
* #param string $indent indentation string
*/
function displayArrayRecursively($arr, $indent='') {
if ($arr) {
foreach ($arr as $value) {
if (is_array($value)) {
//
displayArrayRecursively($value, $indent . '--');
} else {
// Output
echo "$indent $value \n";
}
}
}
}
The code below with display only nested array with values for your specific case (3rd level only)
$tmpArray = array(
array("one", array(1, 2, 3)),
array("two", array(4, 5, 6)),
array("three", array(7, 8, 9))
);
// Scan through outer loop
foreach ($tmpArray as $inner) {
// Check type
if (is_array($inner)) {
// Scan through inner loop
foreach ($inner[1] as $value) {
echo "$value \n";
}
}
}
foreach ($tmpArray as $innerArray) {
// Check type
if (is_array($innerArray)){
// Scan through inner loop
foreach ($innerArray as $value) {
echo $value;
}
}else{
// one, two, three
echo $innerArray;
}
}
Both syntaxes are correct. But the result would be Array. You probably want to do something like this:
foreach ($tmpArray[1] as $value) {
echo $value[0];
foreach($value[1] as $val){
echo $val;
}
}
This will print out the string "two" ($value[0]) and the integers 4, 5 and 6 from the array ($value[1]).
As I understand , all of previous answers , does not make an Array output,
In my case :
I have a model with parent-children structure (simplified code here):
public function parent(){
return $this->belongsTo('App\Models\Accounting\accounting_coding', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Models\Accounting\accounting_coding', 'parent_id');
}
and if you want to have all of children IDs as an Array , This approach is fine and working for me :
public function allChildren()
{
$allChildren = [];
if ($this->has_branch) {
foreach ($this->children as $child) {
$subChildren = $child->allChildren();
if (count($subChildren) == 1) {
$allChildren [] = $subChildren[0];
} else if (count($subChildren) > 1) {
$allChildren += $subChildren;
}
}
}
$allChildren [] = $this->id;//adds self Id to children Id list
return $allChildren;
}
the allChildren() returns , all of childrens as a simple Array .
I had a nested array of values and needed to make sure that none of those values contained &, so I created a recursive function.
function escape($value)
{
// return result for non-arrays
if (!is_array($value)) {
return str_replace('&', '&', $value);
}
// here we handle arrays
foreach ($value as $key => $item) {
$value[$key] = escape($item);
}
return $value;
}
// example usage
$array = ['A' => '&', 'B' => 'Test'];
$result = escape($array);
print_r($result);
// $result: ['A' => '&', 'B' => 'Test'];
array(
"IT"=>
array(
array('id'=>888,'First_name'=>'Raahul','Last_name'=>'Pandey'),
array('id'=>656,'First_name'=>'Ravi','Last_name'=>'Teja'),
array('id'=>998,'First_name'=>'HRX','Last_name'=>'HRITHIK')
),
// array(
"DS"=>
array(
array('id'=>87,'First_name'=>'kalia','Last_name'=>'Pandey'),
array('id'=>6576,'First_name'=>'Raunk','Last_name'=>'Teja'),
array('id'=>9987,'First_name'=>'Krish','Last_name'=>'HRITHIK')
)
// )
)
);
// echo "";
// print_r($a);
echo "";
print_r($a);
?>
////how to get id in place of index value....

php, long and deep matrix

I have a deep and long array (matrix). I only know the product ID.
How found way to product?
Sample an array of (but as I said, it can be very long and deep):
Array(
[apple] => Array(
[new] => Array(
[0] => Array([id] => 1)
[1] => Array([id] => 2))
[old] => Array(
[0] => Array([id] => 3)
[1] => Array([id] => 4))
)
)
I have id: 3, and i wish get this:
apple, old, 0
Thanks
You can use this baby:
function getById($id,$array,&$keys){
foreach($array as $key => $value){
if(is_array( $value )){
$result = getById($id,$value,$keys);
if($result == true){
$keys[] = $key;
return true;
}
}
else if($key == 'id' && $value == $id){
$keys[] = $key; // Optional, adds id to the result array
return true;
}
}
return false;
}
// USAGE:
$result_array = array();
getById( 3, $products, $result_array);
// RESULT (= $result_array)
Array
(
[0] => id
[1] => 0
[2] => old
[3] => apple
)
The function itself will return true on success and false on error, the data you want to have will be stored in the 3rd parameter.
You can use array_reverse(), link, to reverse the order and array_pop(), link, to remove the last item ('id')
Recursion is the answer for this type of problem. Though, if we can make certain assumptions about the structure of the array (i.e., 'id' always be a leaf node with no children) there's further optimizations possible:
<?php
$a = array(
'apple'=> array(
'new'=> array(array('id' => 1), array('id' => 2), array('id' => 5)),
'old'=> array(array('id' => 3), array('id' => 4, 'keyname' => 'keyvalue'))
),
);
// When true the complete path has been found.
$complete = false;
function get_path($a, $key, $value, &$path = null) {
global $complete;
// Initialize path array for first call
if (is_null($path)) $path = array();
foreach ($a as $k => $v) {
// Build current path being tested
array_push($path, $k);
// Check for key / value match
if ($k == $key && $v == $value) {
// Complete path found!
$complete= true;
// Remove last path
array_pop($path);
break;
} else if (is_array($v)) {
// **RECURSION** Step down into the next array
get_path($v, $key, $value, $path);
}
// When the complete path is found no need to continue loop iteration
if ($complete) break;
// Teardown current test path
array_pop($path);
}
return $path;
}
var_dump( get_path($a, 'id', 3) );
$complete = false;
var_dump( get_path($a, 'id', 2) );
$complete = false;
var_dump( get_path($a, 'id', 5) );
$complete = false;
var_dump( get_path($a, 'keyname', 'keyvalue') );
I tried this for my programming exercise.
<?php
$data = array(
'apple'=> array(
'new'=> array(array('id' => 1), array('id' => 2), array('id' => 5)),
'old'=> array(array('id' => 3), array('id' => 4))
),
);
####print_r($data);
function deepfind($data,$findfor,$depth = array() ){
foreach( $data as $key => $moredata ){
if( is_scalar($moredata) && $moredata == $findfor ){
return $depth;
} elseif( is_array($moredata) ){
$moredepth = $depth;
$moredepth[] = $key;
$isok = deepfind( $moredata, $findfor, $moredepth );
if( $isok !== false ){
return $isok;
}
}
}
return false;
}
$aaa = deepfind($data,3);
print_r($aaa);
If you create the array once and use it multiple times i would do it another way...
When building the initial array create another one
$id_to_info=array();
$id_to_info[1]=&array['apple']['new'][0];
$id_to_info[2]=&array['apple']['new'][2];

Categories