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

803 views Asked by At

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
        )
)
2

There are 2 answers

3
Progrock On BEST ANSWER

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
1
mickmackusa On

Allow me to answer the question that was asked. Yes, yes you can... and you nearly had it!

You only needed to change the way that you were accessing the value. Replace the array_shift() call with [0] -- this eliminates the Strict Standards error.

Code: (Demo)

$array=[
    '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";}'
    ]
];
array_walk_recursive($array,function(&$v){$v=unserialize($v)[0];});
var_export($array);

Output:

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