如何在 Laravel 中查询具有精确指定关系的数据集?
Posted
技术标签:
【中文标题】如何在 Laravel 中查询具有精确指定关系的数据集?【英文标题】:How to query dataset with exactly specified relations in Laravel? 【发布时间】:2022-01-04 09:39:23 【问题描述】:我有以下情况:
一个表 product_mappings
和一个表 product_mapping_options
。我现在想查找所有product_mappings
中的所有条目,其中分配了具有特定ID 的条目product_mapping_options
。例如,这可能如下所示:
"data" => array:4 [
0 => array:6 [
"id" => 4
"product_id" => 1
"article_number" => null
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
"product_mapping_options" => array:3 [
0 => array:5 [
"id" => 4
"product_mapping_id" => 4
"product_option_id" => 1
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
1 => array:5 [
"id" => 5
"product_mapping_id" => 4
"product_option_id" => 3
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
2 => array:5 [
"id" => 6
"product_mapping_id" => 4
"product_option_id" => 5
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
]
]
1 => array:6 [
"id" => 5
"product_id" => 1
"article_number" => null
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
"product_mapping_options" => array:4 [
0 => array:5 [
"id" => 7
"product_mapping_id" => 5
"product_option_id" => 1
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
1 => array:5 [
"id" => 8
"product_mapping_id" => 5
"product_option_id" => 3
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
2 => array:5 [
"id" => 9
"product_mapping_id" => 5
"product_option_id" => 5
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
3 => array:5 [
"id" => 10
"product_mapping_id" => 5
"product_option_id" => 7
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
]
]
2 => array:6 [
"id" => 6
"product_id" => 1
"article_number" => null
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
"product_mapping_options" => array:4 [
0 => array:5 [
"id" => 11
"product_mapping_id" => 6
"product_option_id" => 1
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
1 => array:5 [
"id" => 12
"product_mapping_id" => 6
"product_option_id" => 3
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
2 => array:5 [
"id" => 13
"product_mapping_id" => 6
"product_option_id" => 5
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
3 => array:5 [
"id" => 14
"product_mapping_id" => 6
"product_option_id" => 8
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
]
]
3 => array:6 [
"id" => 7
"product_id" => 1
"article_number" => null
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
"product_mapping_options" => array:4 [
0 => array:5 [
"id" => 15
"product_mapping_id" => 7
"product_option_id" => 1
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
1 => array:5 [
"id" => 16
"product_mapping_id" => 7
"product_option_id" => 3
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
2 => array:5 [
"id" => 17
"product_mapping_id" => 7
"product_option_id" => 5
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
3 => array:5 [
"id" => 18
"product_mapping_id" => 7
"product_option_id" => 9
"created_at" => "2021-11-26T09:47:25.000000Z"
"updated_at" => "2021-11-26T09:47:25.000000Z"
]
]
]
]
这里我通过product_mappings
搜索,搜索范围如下:
public function scopeProductOption(Builder $query, ...$productOptionTypeIds): Builder
foreach($productOptionTypeIds as $productOptionTypeId)
$query->whereHas('ProductMappingOptions', function (Builder $query) use ($productOptionTypeId)
$query->where('product_option_id', $productOptionTypeId);
);
return($query);
在示例中,我指定了值 1,3 和 5(然后将其传递到 $productOptionTypeIds
)。
我现在想要什么:我想要 100% 准确地显示 product_mappings
匹配搜索,比如说我想要找到例如只有一个条目恰好映射了 1,3 和 5,而不是 1,3,5 和 7,9 或 11。因此,具有 4 个关系的条目应该消失,因为我不希望条目在某事“结束”了。
你知道我怎样才能“抓住”这个条目吗?所以在上面的例子中,我只想要来自data
的条目0。如果我指定 1、3、5 和 9,我只想要来自 data
的条目 3。
【问题讨论】:
【参考方案1】:好的,找到了解决方案,真的很简单:
public function scopeProductOption(Builder $query, ...$productOptionTypeIds): Builder
$query->has('ProductMappingOptions', '=', count($productOptionTypeIds));
foreach($productOptionTypeIds as $productOptionTypeId)
$query->whereHas('ProductMappingOptions', function (Builder $query) use ($productOptionTypeId)
$query->where('product_option_id', $productOptionTypeId);
);
return($query);
我添加了关系计数
【讨论】:
【参考方案2】:你可以使用whereIn
函数来代替循环语句
public function scopeProductOption(Builder $query, ...$productOptionTypeIds): Builder
//this will parse the values from spread operator
if ($productOptionTypeIds !== [])
if (count($productOptionTypeIds) !== count($productOptionTypeIds, COUNT_RECURSIVE))
$productOptionTypeIds = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($productOptionTypeIds)));
$query->whereHas('ProductMappingOptions', function (Builder $query) use ($productOptionTypeIds)
$query->where('product_option_id', $productOptionTypeIds);
);
return ($query);
【讨论】:
感谢您的回答! :-) 我现在还没有和我一起测试你的解决方案是否会导致我想要的,但在我看来它更复杂,乍一看也不是那么逻辑上可以理解。我发现我的解决方案更易于阅读和理解。以上是关于如何在 Laravel 中查询具有精确指定关系的数据集?的主要内容,如果未能解决你的问题,请参考以下文章
Laravel:如何编写关于 belongsToMany 关系的连接计数查询?