调用模型方法时,Laravel查询太多

时间:2018-01-26 18:19:39

标签: php laravel duplicates

所以我加载所有预算:

$budgets = auth()->user()->budgets()->get(); // With some eager loading and ordering, not needed for this example.

问题在于我在视图中执行某些检查的方式。以此片段为例:

@foreach($budgets as $budget)

    if($budget->getRemainingAmount() < 1) // getRemainingAmount() performs 6 queries
        class="danger"
    @endif

@endforeach

现在我对上述方法有一个主要问题。我不介意6个查询,这就是它在幕后工作的方式,完全没问题。问题是,每次我在视图中调用方法时,都会再次运行6个查询,这意味着它们会一遍又一遍地重复。

我想要做的是,例如,在我的查询中包含该方法,并将其分配给变量。

$budgets = auth()->user()->budgets()->doSomethingToAssignThatMethodToSomeVariable()->get();

现在让我们说这个方法做了以下简单的事情:

public function getRemainingAmount()
{
    return 100;
}

现在,在执行查询时,如何将方法getRemainingAmount()分配给名为$remaining的变量?或者,有没有更好的方法来解决这个问题呢?在我看来,我只想改变这个:

if($budget->getRemainingAmount() < 1)

对此(例如):

if($remaining < 1)

因此,每次调用方法时,我都可以多次执行检查,而不必一遍又一遍地运行6个查询。

有关如何以简单方式实现这一目标的任何想法?我实际上有多种方法导致相同的问题(现在我的调试栏说:66 statements were executed, 41 of which were duplicated, 25 unique)。显然我想删除重复。

1 个答案:

答案 0 :(得分:1)

您可能会对使用缓存存储重复查询结果感兴趣。

  

您甚至可以将Closure作为默认值传递。结果   如果指定的项目不存在,将返回Closure   缓存。传递Closure允许您推迟检索默认值   来自数据库或其他外部服务的值:

$value = Cache::get('key', function () {
    return DB::table(...)->get();
});

您可以控制缓存结果的时间长度,并且可以显着提高性能并减少数据库负载。

为此,访问some-budget-result

$result = Cache::get('some-budget-result', function () {
    return auth()->user()->budgets()->doSomethingToAssignThatMethodToSomeVariable()->get();
});

会运行一次查询,并且每次访问该缓存项时,都会得到相同的结果,没有其他查询。

https://laravel.com/docs/5.5/cache#retrieving-items-from-the-cache