2

我正在编写一个使用三个参数、品牌、型号和燃料类型的搜索功能。'make' 参数是必需的,所以我首先使用下面的代码将品牌及其相关模型选择到一个集合中。


// Find Make and Models
$makeAndModels = Make::where('name', $request->make)->with('carmodels', 'carmodels.fueltype')->first();

此时集合如下所示:

{
    "id": 2,
    "name": "Toyota",
    "created_at": "2020-07-26T16:11:06.000000Z",
    "updated_at": "2020-07-26T16:11:06.000000Z",
    "carmodels": [
        {
            "id": 3,
            "name": "Prius",
            "make_id": 2,
            "fueltype_id": 2,
            "created_at": "2020-07-26T16:44:21.000000Z",
            "updated_at": "2020-07-26T16:44:21.000000Z",
            "fueltype": {
                "id": 2,
                "name": "Hybrid",
                "created_at": "2020-07-26T16:11:06.000000Z",
                "updated_at": "2020-07-26T16:11:06.000000Z"
            }
        },
        {
            "id": 4,
            "name": "Hilux",
            "make_id": 2,
            "fueltype_id": 3,
            "created_at": "2020-07-26T16:44:21.000000Z",
            "updated_at": "2020-07-26T16:44:21.000000Z",
            "fueltype": {
                "id": 3,
                "name": "Diesel",
                "created_at": "2020-07-26T16:11:06.000000Z",
                "updated_at": "2020-07-26T16:11:06.000000Z"
            }
        }
    ]
}

然后我想按名称和燃料类型过滤“carmodels”子集合,将过滤后的数据返回到其原始自身,而不是新集合。这些过滤器应该只在提供了附加参数的情况下运行,我当前使用的代码如下所示。

        //Filter Models By Additional Parameters

            //Model
            if ($request->model) {
                $model = $request->model;
                $makeAndModels->carmodels = $makeAndModels->carmodels->filter()->where('name', $model);
            }

出于某种原因,以这种方式过滤不会覆盖原始集合,例如,如果我过滤到新的子集合中,

        //Filter Models By Additional Paramters

            //Model
            if ($request->model) {
                $model = $request->model;
                $makeAndModels->carmodelsFiltered = $makeAndModels->carmodels->filter()->where('name', $model);
            }

它产生以下结果,所以我知道过滤器应该可以工作。

{
    "id": 2,
    "name": "Toyota",
    "created_at": "2020-07-26T16:11:06.000000Z",
    "updated_at": "2020-07-26T16:11:06.000000Z",
    "carmodelsFiltered": [
        {
            "id": 3,
            "name": "Prius",
            "make_id": 2,
            "fueltype_id": 2,
            "created_at": "2020-07-26T16:44:21.000000Z",
            "updated_at": "2020-07-26T16:44:21.000000Z",
            "fueltype": {
                "id": 2,
                "name": "Hybrid",
                "created_at": "2020-07-26T16:11:06.000000Z",
                "updated_at": "2020-07-26T16:11:06.000000Z"
            }
        }
    ],
    "carmodels": [
        {
            "id": 3,
            "name": "Prius",
            "make_id": 2,
            "fueltype_id": 2,
            "created_at": "2020-07-26T16:44:21.000000Z",
            "updated_at": "2020-07-26T16:44:21.000000Z",
            "fueltype": {
                "id": 2,
                "name": "Hybrid",
                "created_at": "2020-07-26T16:11:06.000000Z",
                "updated_at": "2020-07-26T16:11:06.000000Z"
            }
        },
        {
            "id": 4,
            "name": "Hilux",
            "make_id": 2,
            "fueltype_id": 3,
            "created_at": "2020-07-26T16:44:21.000000Z",
            "updated_at": "2020-07-26T16:44:21.000000Z",
            "fueltype": {
                "id": 3,
                "name": "Diesel",
                "created_at": "2020-07-26T16:11:06.000000Z",
                "updated_at": "2020-07-26T16:11:06.000000Z"
            }
        }
    ]
}

任何人都知道在不创建新集合的情况下过滤集合的子集合的方法吗?提前致谢。

4

1 回答 1

1

with()您可以使用数组作为第一个参数的调用来过滤它们。您可以在哪里查询关系,如果您传递带有包含的键并且closures是查询。这些closures在您的情况下非常通用,我已经在数组之前定义了它,因为这两种情况都是相同的。

这与您现在查询数据库不同,但这具有更好的性能,因为您不必取出所有数据。

$model = $request->model;

$nameFilter = function ($query) use ($model) {
    $query->when($model, function ($query) use ($model) {
        $query->where('name', $model);
    });
};

$makeAndModels = Make::when($model, function ($query) use ($model) {
    $query->where('name', $model);
})->with(
    [
        'carmodels' => $nameFilter,
        'carmodels.fueltype' => $nameFilter,
    ]
)->first();

更新

仅当名称存在时才过滤数据库,Laravelwhen()调用,仅在满足布尔条件时才执行查询。

于 2020-07-30T19:13:36.800 回答