Loop, array_map, array_reduce

This is on refactoring a code that uses foreach loop.  I’ve been using array_map to do similar code refactoring on this case it wasn’t up to job.  Fortunately we have array_reduce!

array_map is good for outputting sequential arrays but if you need to specify the keys, you will need array_reduce.

On this code I’m fetching the plans on Stripe using the excellent Stripe API.  Here’s the JSON format that I want:

{
    "platinum": [
        amount: 100,
        currency: "usd",
        interval: "month",
        name: "platinum",
        trial_period_days: null
    ],
    "gold": [...],
    "silver": [...],
    "free": [...]
}

On my class I have this method:

private function getData()
{
    $plans = \Stripe\Plan::all();

    $output = [];

    foreach ($plans->data as $plan) {
        $output[$plan->id] = [
            $plan->amount / 100,
            $plan->currency,
            $plan->interval,
            $plan->name,
            $plan->trial_period_days,
        ];
    }

    return $output;
}

Adam Wathan has a talk that simplifies code by removing loops so I tried to use array_map instead.

private function getData()
{
    $plans = \Stripe\Plan::all();

    return array_map(function($plan){
        return [
            $plan->amount / 100,
            $plan->currency,
            $plan->interval,
            $plan->name,
            $plan->trial_period_days,
        ];
    }, $plans->data);
}

But I’ve lost the keys on the output.

[
    [
        amount: 100,
        currency: "usd",
        interval: "month",
        name: "platinum",
        trial_period_days: null
    ],
    [...],
    [...],
    [...]
]

Daniel Auener’s post pointed me to the right direction by using array_reduce instead.  So here’s the final version.

private function getData()
{
    $plans = \Stripe\Plan::all();

    return array_reduce($plans->data, function ($output, $plan) {
        $output[$plan->id] = [
            $plan->amount / 100,
            $plan->currency,
            $plan->interval,
            $plan->name,
            $plan->trial_period_days,
        ];
        return $output;
    });
}