Search code examples
phparraysserializationarray-map

PHP Apply multiple callback functions when using array_map, array_walk etc. functions


I have encountered an array of serialized values like below:

Array
(
    [primary] => Array
        (
            [key_type_0_key_name] => a:1:{i:0;s:5:"27232";}
            [key_type_1_key_name] => a:1:{i:0;s:5:"27231";}
            [key_type_2_key_name] => a:1:{i:0;s:5:"27147";}
            [key_type_3_key_name] => a:1:{i:0;s:5:"27157";}
        )

    [additional] => Array
        (
            [key_type_0_key_othername] => a:1:{i:0;s:5:"27169";}
            [key_type_1_key_othername] => a:1:{i:0;s:5:"27160";}
            [key_type_2_key_othername] => a:1:{i:0;s:5:"27103";}
            [key_type_3_key_othername] => a:1:{i:0;s:5:"27149";}
        )
)

Now I need to apply two functions namely, unserialize and array_shift in specified order to extract the scalar values like 27169 and store in another array, how can I do that in one pass of array_map or I have to run array_map two times compulsorily ?

Also one problem is with recursion, only array_walk_recursive handles recursion properly, but in my case if I try below code, I am getting the given error:

return array_walk_recursive($array, function ( &$value ) {
        $value = array_shift( unserialize( $value ) );
    });

Error:

 Strict Standards: Only variables should be passed by reference in /path/to/file.php on line 367

Expected Result:

Array
(
    [primary] => Array
        (
            27232
            27231
            27147
            27157
        )

    [additional] => Array
        (
            27169
            27160
            27103
            27149
        )
)

Solution

  • With no calls to array_map.

    <?php
    
    $data = [
        'primary' =>
        [
            'a:1:{i:0;s:5:"27232";}',
            'a:1:{i:0;s:5:"27231";}',
            'a:1:{i:0;s:5:"27147";}',
            'a:1:{i:0;s:5:"27157";}'
        ],
        'additional' =>
        [
            'a:1:{i:0;s:5:"27169";}',
            'a:1:{i:0;s:5:"27160";}',
            'a:1:{i:0;s:5:"27103";}',
            'a:1:{i:0;s:5:"27149";}'
        ]
    ];
    
    
    
    $numbers = [];
    foreach($data as $key=>$value) {
        foreach($value as $k=>$v) {
            $unserialized = unserialize($v);
            $numbers[$key][] = (int) array_shift($unserialized);
        }
    }
    
    var_dump($numbers);
    

    Output:

    array (size=2)
      'primary' => 
        array (size=4)
          0 => int 27232
          1 => int 27231
          2 => int 27147
          3 => int 27157
      'additional' => 
        array (size=4)
          0 => int 27169
          1 => int 27160
          2 => int 27103
          3 => int 27149
    

    Here a mutating array_walk example with three array_map calls. Far uglier and harder to read in my eyes, but each their own:

    array_walk($data, function(&$v) {
            $v = array_map('intval', array_map('array_shift', array_map('unserialize', $v)));
        }
    );
    var_dump($data);
    

    Output:

        array (size=2)
          'primary' => 
            array (size=4)
              0 => int 27232
              1 => int 27231
              2 => int 27147
              3 => int 27157
          'additional' => 
            array (size=4)
              0 => int 27169
              1 => int 27160
              2 => int 27103
              3 => int 27149