phplaravelmultidimensional-arrayarray-reduce

Laravel/PHP: Add another condition in array_reduce function


I have multidimensional array and I want to sum all the same value with a certain condition.

Here's what my array looks like

$input_taxes = [
    [
        "tax_account_id" => 65,
        "checkbox" => false,
        "amount" => "13950.89",
    ],
    [
        "tax_account_id" => 64,
        "checkbox" => 0,
        "amount" => "1920.70",
    ]
];

What I've researched, they used array_reduce. Below is my code:

$result = array_reduce($input_taxes, function ($carry, $item) { 
    if (! isset($carry[$item['tax_account_id']])) {
        $chart_of_account = ChartOfAccount::where('id', $item['tax_account_id'])
            ->first()
            ->name;
        $carry[$item['tax_account_id']] = [
            'tax_account_id' => $item['tax_account_id'],
            'amount_to_apply' => $item['amount_to_apply'],
            'chart_of_account' => $chart_of_account
        ];
    } else { 
        $carry[$item['tax_account_id']]['amount_to_apply'] += $item['amount_to_apply']; 
    }

    return $carry; 
});

Currently, it will sum all the same values even though it is not checked. Now I want to put a condition where it should be check first before it will sum all the same values.

NOTE: I already tried to put an if statement inside of both if and else statement but unfortunately it didn't work.

Question: How can I add a certain condition within array_reduce?


Solution

  • The check must be inserted at the beginning of your function.

    $result = array_reduce($input_taxes, function ($carry, $item) {
        if (!$item['checkbox']) {
            return $carry;
        }
    
        if (! isset($carry[$item['tax_account_id']])) {
            $chart_of_account = ChartOfAccount::where('id', $item['tax_account_id'])
                ->first()
                ->name;
            $carry[$item['tax_account_id']] = [
                'tax_account_id' => $item['tax_account_id'],
                'amount_to_apply' => $item['amount_to_apply'],
                'chart_of_account' => $chart_of_account
            ];
        } else {
            $carry[$item['tax_account_id']]['amount_to_apply'] += $item['amount_to_apply'];
        }
    
        return $carry;
    });
    

    I can also offer a small optimization to reduce the number of requests to the database

    $chartOfAccountNames = UserProfile::query()
        ->whereIn('id', array_column($input_taxes, 'tax_account_id'))
        ->pluck('name', 'id')
        ->toArray();
    
    $result = array_reduce($input_taxes, static function ($carry, $item) use ($chartOfAccountNames) {
        if (!$item['checkbox']) {
            return $carry;
        }
        if (isset($carry[$item['tax_account_id']])) {
            $carry[$item['tax_account_id']]['amount_to_apply'] += $item['amount'];
    
            return $carry;
        }
    
        $carry[$item['tax_account_id']] = [
            'tax_account_id' => $item['tax_account_id'],
            'amount_to_apply' => $item['amount'],
            'chart_of_account' => $chartOfAccountNames[$item['tax_account_id']],
        ];
    
        return $carry;
    });