As I commented on your own answer, you are on the right track. Actually very close. However, I prefer to use recursion, but this is only a preference, all this could be done in a linear loop.
To find node (read), this works:
function &findnode(array $path, &$collection) { $node = array_shift($path); if (array_key_exists($node, $collection)) { if (count($path) === 0) { // When we are at the end of the path, we return the node return $collection[$node]; } else { // Otherwise, we descend a level further return findnode($path, $collection[$node]); } } throw new RuntimeException('path not found'); } $collection = array( 'foo' => array( 'bar' => array( 'baz' => 'leafnode @ foo.bar.baz' ) ) ); $path = 'foo.bar.baz'; $node =& findnode(explode('.', $path), $collection); var_dump($node); // Output: 'leafnode @ foo.bar.baz'
To introduce node (write), we need to change the logic a bit to create a path along the way.
function &findnode(array $path, &$collection, $create = false) { $node = array_shift($path); // If create is set and the node is missing, we create it if ($create === true && ! array_key_exists($node, $collection)) { $collection[$node] = array(); } if (array_key_exists($node, $collection)) { if (count($path) === 0) { // When we are at the end of the path, we return the node return $collection[$node]; } else { // Otherwise, we descend a level further return findnode($path, $collection[$node], $create); } } throw new RuntimeException('path not found'); } $collection = array( 'foo' => array( 'bar' => array( 'baz' => 'leafnode @ foo.bar.baz' ) ) ); $path = explode('.', 'baz.bar.foo'); $leaf = array_pop($path); // Store the leaf node // Write $node =& findnode($path, $collection, true); $node[$leaf] = 'foo.bar.baz injected'; var_dump($collection); // Will have the new branch 'baz.bar.foo' with the injected value at the leaf
To make it all beautiful and beautiful, you would wrap the read and write operations in your own functions. Most likely, all this is inside your own class.
Thus, using the above version of findnode , we can use these two functions to read and write from / to your collection array.
function read($path, $collection) { $path = explode('.', $path); $val =& findnode($path, $collection); return $val; } function write($value, $path, $collection) { $path = explode('.', $path); $leaf = array_pop($path); $node =& findnode($path, $collection, true); $node[$leaf] = $value; }
NB! This is not a complete solution or the most elegant. But you can probably figure out the rest for yourself.