Laravel一对多一对多关系

时间:2018-09-14 09:34:45

标签: php laravel

目前,我正在使用以下项目:

  • 发票->有很多物品
  • 项目->有许多子项目

我的代码是:

$invoice = Invoice::find($id);
foreach($invoice->items as $item) {
    $item->subItems;
}
return $invoice;

这很好用,直到发票中有太多的项目并且每个项目有太多的子项目并且PHP返回超时。还有其他更好的解决方案吗?

3 个答案:

答案 0 :(得分:1)

首先,我认为您的代码有误。您可能不是$invoice->$items,而是$invoice->items

您的问题的答案可能是急切地加载。代替:

$invoice = Invoice::find($id);

尝试:

$invoice = Invoice::with([
'items' => function ($q) {
    $q->with('subItems');
    }
])->find($id);

这样,所有内容都将在一个查询中加载。您当前正在执行count($invoice->items) + 1个查询。这称为N + 1问题,要意识到这一点非常普遍且重要。

答案 1 :(得分:1)

$invoice = Invoice::with(array('items','items.subItems')->where('id',$id)->get();

答案 2 :(得分:0)

在迭代每一项时,更新set_time_limit所允许的线程时间:

$invoice = Invoice::find($id);
$allowed_seconds_per_row = 3;
foreach($invoice->$items as $item){
    set_time_limit($allowed_seconds_per_row);
    $item->subItems();
}
return $invoice;

这仍然意味着请求将花费大量时间,但是每行迭代只需要$allowed_seconds_per_row秒。如果一行花费的时间比预期的长,则将超时。

其他选项是将进程移至cli并调整最大执行时间以解决最坏的情况。