重构Laravel函数以减少数据库查询的数量


Refactoring Laravel function to reduce number of database queries

我想知道是否有人能为我提供一些关于重构以下函数以减少数据库查询数量的建议?或者,使用Laravel可能有一种完全不同的方式来实现这一点。

我正在尝试计算p&L代表由产品组成的工作,由组件组成:

public function jobProfitAndLoss($id)
{
    $products_in_job = DB::table('job_product')
            ->where('job_id', $id)
            ->get();
    $total_price = 0.0000;
    $total_cost = 0.0000;
    foreach ($products_in_job as $row) {
        $total_price = $total_price + ($row->quantity)*($row->price);
        $product_id = $row->product_id;
        $components_in_product = DB::table('components')
            ->where('product_id', $product_id)
            ->get();
        foreach ($components_in_product as $component) {
            $total_cost = $total_cost + ($component->cost)*($row->quantity);
        }
    }
    return $total_price-$total_cost;
}

产品有组件-

https://www.dropbox.com/s/ncnij8dnh99sb9v/Screenshot%202016-04-09%2015.22.26.png?dl=0

组件属于产品-

https://www.dropbox.com/s/3dx6u30gbod2rv4/Screenshot%202016-04-09%2015.23.43.png?dl=0

工作有很多产品-

https://www.dropbox.com/s/q179t0knd7y8z4k/Screenshot%202016-04-09%2015.24.11.png?dl=0

你会在这里看到,有一些相同的查询被多次执行,我不确定在这种情况下如何避免——

https://www.dropbox.com/s/xonbtx9cdqvq1wd/Screenshot%202016-04-09%2015.33.07.png?dl=0

非常感谢您的帮助。

编辑:您似乎没有使用模型。如果您还没有这样做,请为数据库条目创建模型。您需要为job_product使用protected $table属性,因为Eloquent可能无法自动将类名转换为正确的表名。

首先,如果您还没有建立关系,请建立关系。例如,在Job.php下,包括Products关系:

public function products() {
    return $this->hasMany(App'Products::class); // Assuming App is the namespace
}

现在,您可以直接执行$components_in_product = $products_in_job->products;,而不是使用Fluent查询$components_in_product。然而,这仍然会导致N+1个查询。

因此,请查看以下内容:https://laravel.com/docs/5.2/eloquent-relationships#eager-加载

$books = App'Book::with('author')->get();
foreach ($books as $book) {
    echo $book->author->name; 
} 

对于此操作,将只执行两个查询:

select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)

因此,将$products_in_job更改为Eloquent查询,并将->with('products')添加到该查询中。