If your input is a unique string and therefore clearly identifiable, you can just compare the value (and as you added: the key as well) against the string and if found obtain the path:
$string = 'request type 2';
$path = NULL;
$it = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array), RecursiveIteratorIterator::SELF_FIRST
);
foreach ($it as $key => $value) {
if ($key !== $string and $value !== $string) {
continue;
}
$path = [$string];
for ($count = $it->getDepth(); $count && $count--;) {
array_unshift($path, $it->getSubIterator($count)->key());
}
$path = implode(' -> ', $path);
break;
}
var_dump($path); # string(47) "marketplace -> browse request -> request type 2"
Similar / Related Q&A:
Earlier answer: You are probably missing some points here. First of all you need to clearly identify the element/node (object) you want to find the path to.
You have not outlined in your question how you do that, you only give the array and then the string.
If you mean to have a reference to the node and you want to get the path to it, I give an example how it works in this answer.
First of all, let's reference the object (in the general sense) to get the path from:
// specify the node to search for
$node = &$array['marketplace']['browse request'][1];
As PHP does not allow to identify a string - and your array might contain the same string multiple times - this node needs to be turned into an object which is identifiable. To keep the original string value, it is stored into another variable:
// make the node identifiable (so that it can be searched independent to it's string value, e.g. duplicates)
$string = "$node";
$node = new stdClass();
Now your original array has the node to be searched for to obtain the path from made identifiable. The print_r now looks as the following (shortened):
Array
(
[marketplace] => Array
(
[browse request] => Array
(
[0] => request type 1
[1] => stdClass Object
...
This is necessary because if we search the array and find that object and we keep track of the path used so far in the search we have obtained the path when that object is found.
And this is exactly what we do right now with the help of iterators. PHP already knows how to traverse an array and with a little help from ourselves, this even works with arrays containing objects:
class MyRecursiveIterator extends RecursiveArrayIterator
{
public function hasChildren() {
return is_array($this->current());
}
}
Using this RecursiveIterator
with PHP's standard tree traversal RecursiveIteratorIterator
we can just generate the path in case we find that object:
$path = NULL;
$it = new RecursiveIteratorIterator(new MyRecursiveIterator($array));
foreach ($it as $value) {
if ($value !== $node) {
continue;
}
$path = [$string];
for ($count = $it->getDepth(); $count && $count--;) {
array_unshift($path, $it->getSubIterator($count)->key());
}
$path = implode(' -> ', $path);
break;
}
var_dump($path); # string(47) "marketplace -> browse request -> request type 2"
The full example code at a glance (Demo):
<?php
/**
* get path from child node to parent php array
* @link https://stackoverflow.com/a/18696550/367456
*/
class MyRecursiveIterator extends RecursiveArrayIterator
{
public function hasChildren()
{
return is_array($this->current());
}
}
$array = array(
'marketplace' => array(
'browse request' => array('request type 1', 'request type 2'),
'browse lab',
),
'marketplace2' => array('browse request2', 'browse lab2'),
'submitrequest' => array(''),
'aboutus' => array('')
);
// specify the node to search for
$node = & $array['marketplace']['browse request'][1];
// make the node identifiable (so that it can be searched independent to it's string value, e.g. duplicates)
$string = "$node";
$node = new stdClass();
$path = NULL;
$it = new RecursiveIteratorIterator(new MyRecursiveIterator($array));
foreach ($it as $value) {
if ($value !== $node) {
continue;
}
$path = [$string];
for ($count = $it->getDepth(); $count && $count--;) {
array_unshift($path, $it->getSubIterator($count)->key());
}
$path = implode(' -> ', $path);
break;
}
var_dump($path); # string(47) "marketplace -> browse request -> request type 2"