Laravel Eloquent查询与集合优化

huangapple go评论57阅读模式
英文:

Laravel eloquent query with collection optimization

问题

以下是您控制器中用于显示关于已支付和未支付订单以及相应金额(总额)按年份统计数据的查询。然而,我感到使用的查询可能需要优化,但我无法找到更好的方法来做到这一点。以下是我所拥有的:

public function index(Order $order)
{
    $orders = Order::all()->groupBy(function ($order) {
        return $order->created_at->format('Y');
    })->map(function ($year) {
        return $year->sum('total');
    });
    
    $unpaid_orders = Order::all()->where('payment_confirmed', 0)->groupBy(function ($order) {
        return $order->created_at->format('Y');
    })->map(function ($year) {
        return $year->sum('total');
    });
    
    $paid_orders = Order::all()->where('payment_confirmed', 1)->groupBy(function ($order) {
        return $order->payment_confirmed == false ? $order->year : $order->created_at->format('Y');
    })->map(function ($year) {
        return $year->sum('total');
    });
    
    return view('orders.index', compact('orders', 'unpaid_orders', 'paid_orders'));
}

上面的代码中,我三次查询了Order模型,似乎可以进行优化。

英文:

I have the following queries in my controller to show some statistics about orders paid, and unpaid and the respective amounts (totals), by year. Yet, I feel that the queries I'm using may be optimized but I can't figure out a better way to do it. Here's what I have:

public function index(Order $order)
{
	$orders = Order::all()->groupBy(function ($order) {
		return $order->created_at->format('Y');
	})->map(function ($year) {
		return $year->sum('total');
	});
	
	$unpaid_orders = Order::all()->where('payment_confirmed', 0)->groupBy(function ($order) {
		return $order->created_at->format('Y');
	})->map(function ($year) {
		return $year->sum('total');
	});
	
	$paid_orders = Order::all()->where('payment_confirmed', 1)->groupBy(function ($order) {
		
		return $order->payment_confirmed == false ? $order->year : $order->created_at->format('Y');
	})->map(function ($year) {
		return $year->sum('total');
	});
	
	return view('orders.index', compact('orders', 'unpaid_orders', 'paid_orders'));
}

Above I'm querying the Order model three times which it seems that could be optimized.

答案1

得分: 2

Sure, here is the translated code:

一次执行`$collection = Order::all();`,然后在需要时使用`$collection`

public function index(Order $order)
{
    $collection = Order::all();

    // 或者

    $collection = Order::select(['id', 'payment_confirmed', 'total', 'year', 'created_at'])->get();

    $orders = $collection->groupBy(fn ($order) => $order->created_at->format('Y'))
        ->map(fn ($order) => $order->sum('total'));

    $unpaid_orders = $collection->where('payment_confirmed', 0)
        ->groupBy(fn ($order) => $order->created_at->format('Y'))
        ->map(fn ($order) => $order->sum('total'));

    $paid_orders = $collection->where('payment_confirmed', 1)
        ->groupBy(
            fn ($order) => $order->payment_confirmed == false
                ? $order->year
                : $order->created_at->format('Y')
        )
        ->map(fn ($order) => $order->sum('total'));

    return view('orders.index', compact('orders', 'unpaid_orders', 'paid_orders'));
}

Please note that the code content has been translated, and any code-specific elements remain in the original language.

英文:

Do $collection = Order::all(); once and use $collection wherever you need it.

public function index(Order $order)
{
    $collection = Order::all();

    // OR

    $collection = Order::select(['id', 'payment_confirmed', 'total', 'year', 'created_at'])->get();

    $orders = $collection->groupBy(fn ($order) => $order->created_at->format('Y'))
        ->map(fn ($order) => $order->sum('total'));

    $unpaid_orders = $collection->where('payment_confirmed', 0)
        ->groupBy(fn ($order) => $order->created_at->format('Y'))
        ->map(fn ($order) => $order->sum('total'));

    $paid_orders = $collection->where('payment_confirmed', 1)
        ->groupBy(
            fn ($order) => $order->payment_confirmed == false
                ? $order->year
                : $order->created_at->format('Y')
        )
        ->map(fn ($order) => $order->sum('total'));

    return view('orders.index', compact('orders', 'unpaid_orders', 'paid_orders'));
}

答案2

得分: 0

要优化提供的代码中的查询,您可以在您的订单模型中定义作用域(scopes)。作用域允许您封装可重用的查询逻辑,使代码更容易优化和维护。下面是使用作用域优化的代码版本:

首先,让我们在您的订单模型中定义这些作用域:

class Order extends Model
{
    // ...

    public function scopeUnpaid($query)
    {
        return $query->where('payment_confirmed', 0);
    }

    public function scopePaid($query)
    {
        return $query->where('payment_confirmed', 1);
    }

    public function scopeGroupByYear($query)
    {
        return $query->groupBy(function ($order) {
            return $order->created_at->format('Y');
        });
    }
}

现在,让我们修改index方法以利用这些作用域:

public function index(Order $order)
{
    $orders = Order::groupByYear()->get()->map(function ($year) {
        return $year->sum('total');
    });

    $unpaid_orders = Order::unpaid()->groupByYear()->get()->map(function ($year) {
        return $year->sum('total');
    });

    $paid_orders = Order::paid()->groupByYear()->get()->map(function ($year) {
        return $year->sum('total');
    });

    return view('orders.index', compact('orders', 'unpaid_orders', 'paid_orders'));
}

通过使用作用域,我们可以直接在订单模型上链接必要的条件和分组逻辑,从而产生更干净和更优化的代码。

英文:

To optimize the query in the provided code using scopes, you can define scopes in your Order model. Scopes allow you to encapsulate reusable query logic, making it easier to optimize and maintain your code. Here's an optimized version of the code using scopes:

First, let's define the scopes in your Order model:

class Order extends Model
{
    // ...

    public function scopeUnpaid($query)
    {
        return $query->where('payment_confirmed', 0);
    }

    public function scopePaid($query)
    {
        return $query->where('payment_confirmed', 1);
    }

    public function scopeGroupByYear($query)
    {
        return $query->groupBy(function ($order) {
            return $order->created_at->format('Y');
        });
    }
}

Now, let's modify the index method to utilize these scopes:

public function index(Order $order)
{
    $orders = Order::groupByYear()->get()->map(function ($year) {
        return $year->sum('total');
    });

    $unpaid_orders = Order::unpaid()->groupByYear()->get()->map(function ($year) {
        return $year->sum('total');
    });

    $paid_orders = Order::paid()->groupByYear()->get()->map(function ($year) {
        return $year->sum('total');
    });

    return view('orders.index', compact('orders', 'unpaid_orders', 'paid_orders'));
}

By using scopes, we can chain the necessary conditions and group by logic directly on the Order model, resulting in cleaner and more optimized code.

huangapple
  • 本文由 发表于 2023年6月29日 19:46:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76580738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定