Laravel:将子集合过滤回自身
Laravel: Filter Child Collection Back Into Itself
我正在编写一个搜索函数,该函数使用三个参数:制造商、型号和燃料类型。 '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"
}
}
]
}
有人知道无需创建新集合即可过滤集合子集合的方法吗?提前致谢。
您可以使用数组作为第一个参数使用 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();
更新
为了仅在名称存在时过滤数据库,Laravel
调用了 when()
,仅在满足布尔条件时才执行查询。
我正在编写一个搜索函数,该函数使用三个参数:制造商、型号和燃料类型。 '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"
}
}
]
}
有人知道无需创建新集合即可过滤集合子集合的方法吗?提前致谢。
您可以使用数组作为第一个参数使用 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();
更新
为了仅在名称存在时过滤数据库,Laravel
调用了 when()
,仅在满足布尔条件时才执行查询。