Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I would like to convert ($data):

Array
(
    [login] => Log in
    [logout] => Log out

    [label] => Array
        (
            [email] => test@test.com 
            [name] => Some name
        )

    [controllers] => Array
        (
            [page] => Array
                (
                    [title_new] => New page 
                    [title_edit] => Edit page
                    [submit_button] => Submit page
                )
        )
)

To ($result):

Array
(
    [login] => Log in
    [logout] => Log out
    [label[email]] => test@test.com
    [label[name]] => Some name
    [controllers[page][title_new]] => New page
    [controllers[page][title_edit]] => Edit page
    [controllers[page][submit_button]] => Submit page
 )

The following code works "fine" :

$data = some_data;
$result = array();

foreach ($data as $k => $v) {
  if (is_array($v))
    foreach ($v as $_k => $_v)
      if (is_array($_v))
        foreach ($_v as $__k => $__v)
          if (is_array($__v))
            foreach ($__v as $___k => $___v)
              $result[$k.'['.$_k.']['.$__k.']['.$___k.']'] = $___v;
          else
            $result[$k.'['.$_k.']['.$__k.']'] = $__v;
      else
        $result[$k.'['.$_k.']'] = $_v;
  else
    $result[$k] = $v;
}

It works "Fine" as in.. for a few levels it goes alright but if you need to go deeper it shows "Array" as the value. So I probably need some kind of recursion, but I have no clue how to get around that with PHP :(

Codereview can you help me!?

share|improve this question
2  
I think this question should go to stackoverflow since codereview is about reviewing code that actualy work. – Jean-François Côté Aug 14 '12 at 21:03
Well it works for 4 levels deep atleast, which is most likely all I need. – Tessmore Aug 14 '12 at 21:04
@Tessmore If that's all you need then what are you asking for? Don't add something unless you actually need it. – James Khoury Aug 15 '12 at 5:46
1  
I don't see the point of code-review then, I want to improve my code and not stick with 'this is good enough for now' – Tessmore Aug 15 '12 at 10:35
Both valid points. This seems like a "problem" which is usually more SO's field, but the fact that you want to learn a better way proves that its ok here. One improvement I see would be to add some braces {} on those statements. That could be part of the reason this doesn't work right here. I've not looked through this to be sure though. – mseancole Aug 15 '12 at 21:21
show 1 more comment

closed as off topic by Corbin, James Khoury, svick, codesparkle, Quentin Pradet Sep 17 '12 at 8:40

Questions on Code Review Stack Exchange are expected to relate to code review request within the scope defined in the FAQ. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about closed questions here.

1 Answer

up vote 2 down vote accepted

So I probably need some kind of recursion, but I have no clue how to get around that with PHP

Recursion in PHP is the same as basically any language (well... at a very high level).

I'm very torn on if I think your question is on topic or not, but it's been a long time since I've written anything recursive, and I'm a shameless rep-whore, so here's my go:

function flatten(array $arr, $prefix = '')
{
    $out = array();
    foreach ($arr as $k => $v) {
        $key = (!strlen($prefix)) ? $k : "{$prefix}[{$k}]";
        if (is_array($v)) {
            $out += flatten($v, $key);
        } else {
            $out[$key] = $v;
        }
    }
    return $out;
}

Or, if you don't like the magical second param:

function _flatten(array &$out, array $arr, $prefix)
{
    foreach ($arr as $k => $v) {
        $key = (!strlen($prefix)) ? $k : "{$prefix}[{$k}]";
        if (is_array($v)) {
            _flatten($out, $v, $key);
        } else {
            $out[$key] = $v;
        }
    }
}

function flatten(array $arr)
{

    $flat = array();
    _flatten($flat, $arr, '');
    return $flat;

}

You could also optimize a bit and make a lot of the things in there references (the for loop values and function params). I tend to avoid references in PHP though unless I have an extremely strong reason for them. (If you plan on using this function on arrays larger than a few hundred elements, that may begin to enter into strong reason land.)

(And flatten is a horrible name, but... yeah.)

share|improve this answer
Hey, that works pretty great. Usually the arrays are indeed bigger than a few hundred elements, but not like thousands. I will try to get some benchmarks on them. Thanks! – Tessmore Aug 15 '12 at 10:46
Well very simple tests do show that $key = $prefix ? $k : "{$prefix}[{$k}]"; is a lot faster then the !strlen() check. Why do you use that? Other than that it looks fast enough to me. – Tessmore Aug 15 '12 at 11:00
@Tessmore Because 0 is a valid key and considered false. I suppose a faster version than strlen could be ((string) $prefix) !== ''). Or, the fastest would probably actually be to have $prefix default to null and just check $prefix === null. – Corbin Aug 15 '12 at 11:02
Ye I did the last one – Tessmore Aug 15 '12 at 11:03

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