Laravel Spatie 按关系最后一个元素自定义过滤器

Laravel Spatie Custom Filter by Relation Last Element

我有一个动物模型。动物关系检查和疾病模型。我需要过滤生病的动物。

考试模式有disease_id。如果最后一个检查对象 disease_id 不等于 null,则该动物生病了。我正在尝试使用 spatie 过滤器对其进行过滤。

这是我的自定义过滤器代码:

这必须按上次检查数据过滤。但是通过所有检查数据过滤。

<?php

use Spatie\QueryBuilder\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

class SickAnimalsFilter implements Filter
{
    public function __invoke(Builder $query, $value, string $property)
    {
            $query->whereHas('examinations', function($q) {
                $q->orderBy('created_at', 'DESC')->limit(1)->where('disease_id', '!=', null);
            });
    }
}

示例数据:

这应该包含在过滤中。这只动物现在病了。

"examinations": [
            {
                "id": 1,
                "animal_id": 1,
                "disease_id": 1
                "created_at": "2022-01-28T09:24:46.000000Z",
                "updated_at": "2022-01-28T09:24:46.000000Z",
            }
        ]

这不应包含在筛选中。这只动物以前生病了,现在好了。

"examinations": [
            {
                "id": 1,
                "animal_id": 1,
                "disease_id": 1
                "created_at": "2022-01-28T09:24:46.000000Z",
                "updated_at": "2022-01-28T09:24:46.000000Z",
            },
            {
                "id": 2,
                "animal_id": 1,
                "disease_id": null
                "created_at": "2022-01-30T15:29:00.000000Z",
                "updated_at": "2022-01-30T15:29:00.000000Z",
            }
        ]

我解决了这个问题:

<?php

use App\Models\Examination;
use Spatie\QueryBuilder\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

class SickAnimalsFilter implements Filter
{
    public function __invoke(Builder $query, $value, string $property)
    {
        $examinationIds = $query->withMax('examinations', 'id')->get()->pluck('examinations_max_id');
        $animalIds = Examination::query()->groupBy('animal_id', 'id')->get()->whereIn('id', $examinationIds)->where('disease_id', '!=', null)->pluck('animal_id');
        $query->whereIn('id', $animalIds);
    }
}

我得到了每只动物的最后一次检查 ID 并写信给 $examinationIds

并使用 $examinationIds 过滤考试。 过滤后使用 pluck('animal_id').

获取动物 ID

然后用$animalIds过滤$query