Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Let's say I have the following string in my variable:

$arr['data_|_multilanguage_|_en_|_field'] = 23;

I want to transform that into a multidimensional array as follows:

$arr['data']['multilanguage']['en']['field'] = 23;

I did a recursive function

foreach ($arr as $outer_key => $outer_value) {

    $parts = explode('_|_', $outer_key);

    $reference =& $arr;
    $final_key = count($parts) - 1;

    foreach ($parts as $key => $part) {
        if (!$final_key == $key) {

            if (empty($reference[$part])) {
                $reference[$part] = array();
            }

            $reference =& $reference[$part];

        } else {
            $reference[$part] = $arr[$str];
            unset($arr[$outer_key]);
        }
    }
}

The problem is that the var_dump shows that the children are reference. Is there a better way?

share|improve this question
3  
btw your function is iterative, not recursive ; )) –  moonwave99 May 27 at 13:50
2  
possible duplicate of: 628176/using-a-string-path-to-set-nested-array-data –  Ryan Vincent May 27 at 13:58
1  
stackoverflow.com/questions/7851590/… separator aside ^^ –  moonwave99 May 27 at 13:59

3 Answers 3

<?php
$arr = array();
$arr['data_|_multilanguage_|_en_|_field'] = 23;
$arr['data_|_multilanguage_|_en_|_field2'] = 32;
$arr['data_|_multilanguage_|_fr_|_field'] = 57;
$arr['data_|_test'] = 57;
$arr['data_|_testing_|_var'] = 57;

function doArray(&$newarr,$keys,$value) {
    if(count($keys) > 1) {
        $key = array_shift($keys);

        if(!isset($newarr[$key]) || !is_array($newarr[$key])) {
            $newarr[$key] = array();
        }

        doArray($newarr[$key],$keys,$value);
    } else {
        $newarr[array_shift($keys)] = $value;
    }
}

$newarr = array();
foreach($arr AS $key => $value) {
    $keys = explode("_|_",$key);

    doArray($newarr,$keys,$value);
}

echo '<pre>';
print_r($newarr);
echo '</pre>';
?>
share|improve this answer

You just have a wrong if() statement :

 if (!$final_key == $key) {}

! will be evaluated before ==.
Change it for :

 if ($final_key != $key) {}

(you've got another little issue in your final $reference[$part] = assignment, I corrected it in the following code)

$arr['data_|_multilanguage_|_en_|_field'] = 23;

foreach ($arr as $outer_key => $outer_value) {

    $parts = explode('_|_', $outer_key);

    $reference =& $arr;
    $final_key = count($parts) - 1;

    foreach ($parts as $key => $part) {

        if ($final_key != $key) { 

            if (empty($reference[$part])) {
                $reference[$part] = array();
            }

            $reference =& $reference[$part];

        } else {
            $reference[$part] = $outer_value;
            unset($arr[$outer_key]);
        }
    }
}

And here is your result !

array(1) {
  ["data"]=>
  array(1) {
    ["multilanguage"]=>
    array(1) {
      ["en"]=>
      &array(1) {
        ["field"]=>
        int(23)
      }
    }
  }
}
share|improve this answer
    
and $reference[$part] = $arr[$str]; should be $reference[$part] = $outer_value; –  palindrom May 27 at 13:57
    
@palindrom I just saw it while writing my post, thanks. –  zessx May 27 at 13:59
    
thanks this solution (with some minor modifications) it worked for a problem I was having :) –  mic May 29 at 13:03

This should work I think, pass in your (existing) array, wanted key (why not use dot notation instead of '_|_' ?), and your desired value

function array_set(&$array, $key, $value)
    {
        if (is_null($key)) return $array = $value;

        $keys = explode('_|_', $key);

        while (count($keys) > 1)
        {
            $key = array_shift($keys);

            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if ( ! isset($array[$key]) || ! is_array($array[$key]))
            {
                $array[$key] = array();
            }

            $array =& $array[$key];
        }

        $array[array_shift($keys)] = $value;

        return $array;
    }
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.