1

I'm trying to cross join arrays to automatically create data for various test scenarios in an app. Here are the arrays to be cross joined (note that $base['sales'] has had some elements stripped out of it to simplify it for posting this question):

$base['sales'] = ['shirts'=>1200.0, 'pants'=>1000.0, 'socks'=>1700.0];

$scenarioIDs = range(1, 5);

The end result is supposed to look like this:

$data[1]['sales'] = ['shirts'=>1200.0, 'pants'=>1000.0, 'socks'=>1700.0];
$data[2]['sales'] = ['shirts'=>1200.0, 'pants'=>1000.0, 'socks'=>1700.0];
$data[3]['sales'] = ['shirts'=>1200.0, 'pants'=>1000.0, 'socks'=>1700.0];
$data[4]['sales'] = ['shirts'=>1200.0, 'pants'=>1000.0, 'socks'=>1700.0];
$data[5]['sales'] = ['shirts'=>1200.0, 'pants'=>1000.0, 'socks'=>1700.0];

I have tried this:

    $data = [];
    array_map(function($scenarioID) {
        $data[$scenarioID]['sales'] = $base['sales'];
    }, $scenarioIDs);
echo '<pre>' . print_r($data, 1) . '</pre>';    
exit();

but get the message Undefined variable: base in C:\xampp\htdocs\Sales\index.php on line 72 five times (one for each scenarioID).

I keep thinking there must be a way to do this without using loops. Does anyone know how?

Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
knot22
  • 2,648
  • 5
  • 31
  • 51

1 Answers1

1

To use a variable from the exterior context within your anonymous function, you need the use keyword:

array_map(
  function($id) use ($base, &$data) {/* fill out the function */},
  $scenarioIDs
);

This syntax will make a copy of $base at the time the function is first invoked, so if you make changes to $base and try to use the same custom mapper, the new values of $base will not be reflected. So, if you need the anonymous function to always work with the current value of $base, then pass that argument by reference as I did with $data:

function($id) use (&$base, &$data) {}

From the docs:

Closures may also inherit variables from the parent scope. Any such variables must be passed to the use language construct.

As a sidenote, array_map is meant to transform the supplied array ($scenarioIDs in your case) into a different array. You aren't really using it as it was meant. If all you want to do is attach the scenario ids as keys to $data, just use this one-liner:

foreach($scenarioIDs as $id) $data[$id]['sales'] = $base['sales'];
BeetleJuice
  • 39,516
  • 19
  • 105
  • 165