phparraysarray-walk

walk through array with nested output in PHP


I have this code:

foreach ($_POST as $key1 => $item1):
    if (is_array($item1)):
        foreach ($item1 as $key2 => $item2):
            if (is_array($item2)):
                foreach ($item2 as $key3 => $item3):
                    if (is_array($item3)):
                        foreach ($item3 as $key4 => $item4):
                            $_POST[$key1][$key2][$key3][$key4] = empty($item4) ? NULL : $item4;
                        endforeach;
                    else:
                        $_POST[$key1][$key2][$key3] = empty($item3) ? NULL : $item3;
                    endif;
                endforeach;
            else:
                $_POST[$key1][$key2] = empty($item2) ? NULL : $item2;
            endif;
        endforeach;
    else:
        $_POST[$key1] = empty($item1) ? NULL : $item1;
    endif;
endforeach;

$_POST is a 4 level array, array_walk() would return my array in first level (which I don't want).

The Question is how can I simplify this code with repeating blockes?


Solution

  • This is a job for recursion, most easily implemented here with array_walk_recursive.

    Make sure that you understand what your code does though, empty returns true for zeros, which could be a problem.

    $input = [
        'param1' => [
            'sub1_1' => [
                'sub1_1_1' => [
                    'sub1_1_1_1' => 'foo',
                    'sub1_1_1_2' => '',
                    'sub1_1_1_3' => 0,
                    'sub1_1_1_4' => 'bar',
                    'sub1_1_1_5' => false,
                    'sub1_1_1_6' => [
                        'sub1_1_1_6_1' => 'baz',
                        'sub1_1_1_6_2' => ''
                    ]
                ]
            ]
        ]
    ];
    
    array_walk_recursive($input, function(&$value)
    {
        $value = (empty($value)) ? null:$value;
    });
    
    // Verify that false-y values were changed to null
    assert($input['param1']['sub1_1']['sub1_1_1']['sub1_1_1_2']===null, 'Empty string should be normalized to null');
    assert($input['param1']['sub1_1']['sub1_1_1']['sub1_1_1_3']===null, 'Zero should be normalized to null');
    assert($input['param1']['sub1_1']['sub1_1_1']['sub1_1_1_5']===null, 'False should be normalized to null');
    
    // Check out the state of the normalized input
    var_dump($input);