php Laravel使用filter和map代替foreach

o75abkj4  于 2023-10-15  发布在  PHP
关注(0)|答案(3)|浏览(164)

我有两个型号,PlanTransactions。每个Plan可以有多个Transactions。我想获取与所有计划相关的所有交易的总金额。现在我是这样做的:

$plans = $this->plan->with('transactions')->get();

    $total = [];

    foreach($plans as $plan)
    {
        foreach($plan->transactions as $transaction)
        {
            $total[] = $transaction->amount;
        }
    }

    dd(array_sum($total)); // Works, I get the total amount of all transactions that are related to a Plan.

但是我想去掉foreach循环,改用filter和/或map。我尝试了以下方法:

$test = $plans->filter(function ($plan) {
        return $plan->has('transactions');
    })->map(function ($plan) {
        return $plan->transactions;
    })->map(function ($transaction) {
        return $transaction; // Not sure what to do here, $transaction->amount doesn't work
    });

我在最后一点卡住了,我最终得到了一个集合。有什么想法可以实现这一点,至少不使用foreach循环?也许在查询本身?
所以我有几个Plans,每个Plan可以有很多个Transactions。每个Transaction都有一个amount字段,我在其中存储每个Transaction的数量。我想获取与计划相关的所有交易的总金额。所以,交易的总和。

mbjcgjjk

mbjcgjjk1#

假设你已经有了一个计划,该计划的transactions属性将是一个集合,所以你可以对它使用sum()方法:

$total = $plan->transactions->sum('amount');

因为它只是一个特定的计划,所以你是否渴望加载它并不重要。但是如果它还没有被加载,你可以通过数据库来完成:

$total = $plan->transactions()->sum('amount');

如果你有一系列的计划,使用reduce()

$total = $plans->reduce(function ($carry, $plan) {
    return $carry + $plan->transactions->sum('amount');
}, 0);

在这种情况下,您确实希望即时加载事务以减少查询的数量。(否则,请参考上述数据库。)
如果你来自一个查询,你可以使用连接或双重查询-后者通常更简单:

$ids = Plan::where('condition')->pluck('id')->all();
$total = Transaction::whereIn('plan_id', $ids)->sum('amount');

当然,如果你只是想要总金额,无论如何,根本没有必要通过计划。:)

$total = Transaction::sum('amount');
laawzig2

laawzig22#

由于您有计划ID,因此可以使用sum()方法:

$this->transaction->where('plan_id', $planId)->sum('amount');

要计算所有交易的金额,请删除where()部分。
要计算多个计划的金额,请使用whereIn() intsead of where()

js81xvg6

js81xvg63#

Assuming you already have a plan, the transactions property on that plan will be a collection, so you can use the sum() method on that:

$total = $plan->transactions->sum('amount');
Since it's just one specific plan, it doesn't matter whether you eager load it or not. But if it hasn't been loaded already, you can just do it through the database instead:

$total = $plan->transactions()->sum('amount');
If you have a collection of plans, use reduce():

$total = $plans->reduce(function ($carry, $plan) {
    return $carry + $plan->transactions->sum('amount');
}, 0);
In this case, you do want to eager load the transactions to reduce the number of queries. (Otherwise, please refer to the above on going through the database instead.)

If you're coming from a query, you can either use joins or double queries - the latter is generally simpler:

$ids = Plan::where('condition')->pluck('id')->all();
$total = Transaction::whereIn('plan_id', $ids)->sum('amount');
And, of course, if you just want the total amount no matter what, there's no need to go through the plans at all. :)

$total = Transaction::sum('amount');

相关问题