在laravel 5.8中优化请求

时间:2019-04-22 11:09:25

标签: php laravel laravel-5

自昨天以来,我因无法解决的要求而陷入困境。 我创建了一个站点来管理废弃的狗窝。 狗必须接种疫苗:

  • 这是他们人生中的第一次,然后一个月后提醒您
  • 然后每年一次

因此,我要从“动物”表和“ soinsveto”表中查找所有一年以上未接种疫苗的狗,或者这是自一个月以来首次接种疫苗的狗。

目标是在管理界面中显示一条警报,提示“注意,这只狗没有接种疫苗,应该早于...)

我的桌子“动物”

id | name |

我的表“ soinveto”(如果是第一种疫苗,则类型soin_id = 1,如果下一种疫苗,则延迟一个月,如果是一年,则延迟为2

id | typesoin_id | animal_id | datedusoin

动物模型

public function soinsvetos() {
    return $this->hasMany(Soinsveto::class, 'animal_id');
}

soinveto模型

public function animal()
{
    return $this->belongsTo(Animal::class, 'animal_id')->withTrashed();
}

我要选择:

  • 按日期(“ datedusoin”字段)进行最后一次接种的所有动物(“食用动物”)(typesin_id = 1或2的“ soinsvetos”表)。我更喜欢用日期,因为使用者有可能在这种疾病中抓住疫苗。努力工作,以免出现“ id”危险。

  • 然后如果“ typesoin_id”为1,我检查到今天的日期不超过一个月,如果为2,则不超过一年。

我找到了一个可行的解决方案,但完全没有经过优化:

public function compose(View $view)
{

    foreach (\App\Animal::get()
                 ->all() as $animal) {

        $soins = \App\Soinsveto::with('typesoin')
            ->where('animal_id', $animal->id)
            ->where(function ($q) { /// 1 = primovaccin et 2 = vaccins annuels
                $q->where('typesoin_id', '=', '2')
                    ->orWhere('typesoin_id', '=', '1');
            })
            ->orderBy('datedusoin', 'desc')
            ->get()
            ->first();
        if ($soins) {

            if ($soins->typesoin_id == '1' && $soins->datedusoin < Carbon::now()->subMonths(1)) {
                $crudFieldValue = Carbon::parse($soins->getOriginal('datedusoin'))->addyear(1)->toDateString();

            }
            if ($soins->typesoin_id == '2' && $soins->datedusoin < Carbon::now()->subYears(1)) {
                $crudFieldValue = Carbon::parse($soins->getOriginal('datedusoin'))->addyear(1)->toDateString();

            }

        }
        $notif[] = [
            'title' => $soins->typesoin->nomsoin,
            'start' => $crudFieldValue,
            'nomanimal' => $animal->nom,
        ];
    }
    $view->with('notif', $notif);


}

在我的版本中,所有的动物都被加载,这会产生大量的sql请求。 我找不到任何解决方案来实现这一目标。我做了很多尝试,但无法在单个优化查询中将所有内容汇总在一起

1 个答案:

答案 0 :(得分:0)

在我对问题的评论之后,建议您将foreach语句重写为以下代码。它使用with函数渴望在所有动物中加载soinsvetos关系,这样您就不会遇到N + 1问题。

foreach (\App\Animal::with('soinsvetos')->get() as $animal) {

    $soins = $animal->soinsvetos
                    ->filter(function ($soinsveto) {
                        /// 1 = primovaccin et 2 = vaccins annuels
                        return $soinsveto->typesoin_id == 1 || $soinsveto->typesoin_id == 2;
                    })
                    ->sortBy('datedusoin', 'desc')
                    ->first();

    if ($soins) {
        if ($soins->typesoin_id == '1' && $soins->datedusoin < Carbon::now()->subMonths(1)) {
            $crudFieldValue = Carbon::parse($soins->getOriginal('datedusoin'))->addyear(1)->toDateString();
        }
        if ($soins->typesoin_id == '2' && $soins->datedusoin < Carbon::now()->subYears(1)) {
            $crudFieldValue = Carbon::parse($soins->getOriginal('datedusoin'))->addyear(1)->toDateString();
        }
    }

    $notif[] = [
        'title' => $soins->typesoin->nomsoin,
        'start' => $crudFieldValue,
        'nomanimal' => $animal->nom,
    ];

}