0

Here is my precode...

$keys = array('a', 'b', 'c', 'd');
$number = 10;

And here is my code...

eval('$array[\''.implode('\'][\'',$keys).'\'] = $number;');

Using this, I get the following result...

Array (
    [a] => Array
        (
            [b] => Array
                (
                    [c] => Array
                        (
                            [d] => 10
                        )
                )
        )
)

Now, the problem is that this is the exact result I want, but I don't want to use eval().

As input to my code, I have a list of keys and a number. The number should be set to the value of the keys array being used to generate child-based keys for a certain array $array.

Is there a different way that I can achieve this? I don't want to overwrite the keys/numbers with new values as the code works - eval() preserves this already, so my new code should do the same.

2
  • There is a point where I have to ask why in the world you're doing this before I'll answer the question. Why would you want this structure? And is having such a rigid structure actually damaging your project? Surely there must be better storage methods in existence? Commented Dec 29, 2009 at 16:10
  • i'd have to spend about an hour writing up the full explanation of what unique situation has arisen for this requirement. sorry. Commented Dec 29, 2009 at 16:28

3 Answers 3

3

Please note that the code below (which you evaluate) will generate a warning, and will therefore not work on projects with error reporting up to the max:

$array = array();
$array['a']['b'] = 42; // $array['a'] is not an array... yet

Since you're using PHP 5, you can work with references to manipulate your array while traversing the branch of your tree that you wish to modify.

$current = & $array;

foreach ($keys as $key):

  if (!isset($current[$key]) || !is_array($current[$key]))
    $current[$key] = array();

  $current = & $current[$key];

endforeach;

$current = $value;

Edit: corrected for avoiding warnings and conflicts.

Sign up to request clarification or add additional context in comments.

2 Comments

So why doesn't it throw an error on the second round where you effectively set $array['a'] = $array['b'] since a is not an array yet either. Anyway, +1 since this works great and is way shorter than my answer.
firstly, what error does it generate? i have my reporting up the max, including deprecation warnings, and i dont see anything. your code works for cases where array is empty or with keys that aren't a potential conflict. but if the array looks like this: array('a' => 'b') and the keys looks like this array('a', 'orange') I get: Fatal error: Cannot create references to/from string offsets nor overloaded objects in ...
1

Here is a full code example showing how it would work. Whats important is that you use a reference to the array so you can modify it:

<?php
    $keys = array('a', 'b', 'c', 'd'); 
    $number = 10;

    $org_array = array(
        "a" => "string",
        "z" => array( "k" => false)
      );

    function write_to_array(&$array, $keys, $number){
      $key = array_shift($keys);
      if(!is_array($array[$key])) $array[$key] = array();
      if(!empty($keys)){
        write_to_array($array[$key], $keys, $number);
      } else {
        $array[$key] = $number;
      }
    }

    write_to_array($org_array, $keys, $number);

    print_r($org_array);
?>

3 Comments

this ones the closest, but again, doesn't work for the case where the array is: array('a' => 'meow') and the keys array is: array('a', 'b', 'c'). I get a Fatal error: Only variables can be passed by reference...
@onassar I misunderstood what you meant by previous values. I updated two parts in the code, the $org_array['a'] is now set to a string to test, and I changed the isset test to an is_array test. Now if the key exists as something other than an array is is overwritten vs. extended.
follow up: what about this case for deletion: eval('unset($array[\''.implode('\'][\'',$keys).'\']);'); ?
1
function deepmagic($levels, $value)
{
    if(count($levels) > 0)
    {
        return array($levels[0] => deepmagic(array_slice($levels, 1),
            $value));
    }
    else
    {
        return $value;
    }
}

$a = deepmagic(Array('a', 'b', 'c', 'd'), 10);

var_dump($a);

Output:

array(1) {
  ["a"]=>
  array(1) {
    ["b"]=>
    array(1) {
      ["c"]=>
      array(1) {
        ["d"]=>
        int(10)
      }
    }
  }
}

2 Comments

That one doesn't work for array's with existing keys/values either. Hmmm.
So then use array_keys() or array_values() as desired before passing the array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.