views:

196

answers:

6

Does anybody see anything wrong with the following function? (Edit: no, I don't think anything is wrong, I am just double-checking since this will be inserted into a very common code path.)

function getNestedVar(&$context, $name) {
    if (strstr($name, '.') === FALSE) {
        return $context[$name];
    } else {
        $pieces = explode('.', $name, 2);
        return getNestedVar($context[$pieces[0]], $pieces[1]);
    }
}

This will essentially convert:

$data, "fruits.orange.quantity"

into:

$data['fruits']['orange']['quantity']

For context, this is for a form utility I am building in Smarty. I need the name for the form also so I need the string to be in a key-based form, and can't directly access the Smarty variable in Smarty.

+1  A: 

I don't see anything wrong with that code. I've tested it as well.

Does that answer your question?

Edit: This is IMHO slightly nicer. It doesn't use recursion, and returns null in case a child of a non-array is accessed.

function getNestedVar(array $array, $name) {
   $name = explode('.', $name);
   foreach($name as $namePart) {
      if (is_array($array)) return null;
      if (!isset($array[$name])) return null;
      $array = $array[$name];
   }

   return $array;
}

Cheers

Evert
A: 

why u need to return this

return $context[$name];

only use

return ;

is quite good , because you send to function the array by reference and the function change it.

Haim Evgi
That wouldn't work without rearranging the recursion, since the last array lookup happens inside the base case.
Renesis
+1  A: 

How deep will this nesting be? PHP has a limit on recursion, seems to be ca. 2^16. Just tested this and at recursion depth 65420 PHP (5.2.9) silently failed (no error).

GodsBoss
Certainly not that deep but that is good to know.
Renesis
+2  A: 

Try an iterative approach:

function getNestedVar(&$context, $name) {
    $pieces = explode('.', $name);
    foreach ($pieces as $piece) {
        if (!is_array($context) || !array_key_exists($piece, $context)) {
            // error occurred
            return null;
        }
        $context = &$context[$piece];
    }
    return $context;
}
Gumbo
I like it... only one use of explode will occur and no strstr checks. Way less string parsing going on than mine.
Renesis
A: 

In its current form no error/warnings are shown if one or more elements do not exist

error_reporting(E_ALL|E_STRICT); ini_set('display_errors', 1);
$x = array();
getNestedVar($x, '1.2.3.4');
echo 'done.';

(tested with php 5.3.1/win32).
For some reason accessing a non-existing element in getNestedVar($context[$pieces[0]]... does not raise a warning message, which makes it really hard to debug and to find e.g. a typo.

VolkerK
Correct... I just want null returned if it does not exist, as it would with standard array access.
Renesis
...which is fine. I was just baffled that php itself does not raise a warning.
VolkerK
A: 

Why you not just make use of html.. name="fruit[orange]" is enough.. to make an array.

Chris