英文:
Laravel whereHas only bring back models that match criteria
问题
I understand that you want assistance with a Laravel code issue. It seems you're trying to retrieve specific models based on certain criteria. However, you're encountering issues where models without matching options are still being returned.
Here's your original code for reference:
$buyers = Buyer::with([
'tiers.options'
])->whereHas('tiers.options', function ($query) {
$query->where([
['type', 'private']
]);
})->get();
It appears that you want to filter only the models that have options with a type of "private." However, this code may not be working as expected.
One thing to check is your database relationships and whether they are correctly set up. Ensure that the relationships between buyers, tiers, and options are correctly defined in your models.
Also, make sure that the column names in your database match the conditions you're specifying in your code.
If you've already verified these aspects and are still facing issues, you might consider using Laravel's whereHas
with a closure to filter the results more precisely. Here's an example:
$buyers = Buyer::with('tiers.options')
->whereHas('tiers.options', function ($query) {
$query->where('type', '=', 'private');
})
->get();
This code explicitly checks if the "type" column in the related options table is equal to "private."
If you continue to experience issues, please provide more information about your database structure and Laravel models, which could help in diagnosing the problem further.
英文:
I'm working in a Laravel 10 project and need to just return tier's where each tier's options matches some criteria. Right now I need to do it based on a column called type
. For reference, I only have 2 entries in my table out of around 700 that should match "private", but when I use a whereHas
and set the where
to pull back records that match private, I get everything returned.
If I change "private" to something that doesn't exist, I get nothing.
What am I missing here to just return models that match a set of criteria and then don't load tier options and tiers where options don't match?
$buyers = Buyer::with([
'tiers.options'
])->whereHas('tiers.options', function ($query) {
$query->where([
['type', 'private']
]);
})->get();
Here's an example of what I mean by options
being returned with an empty array:
{
"model": null,
"metadata": {
"model_count": 1,
"model_data": [
{
"id": 3,
"user_id": 1,
"company_id": 1,
"name": "FakeBuyer",
"description": "A collection of dummy and faker buyer tiers.",
"is_default": false,
"is_enabled": true,
"last_used_at": "2023-04-18T09:59:50.000000Z",
"created_at": "2023-04-17T13:41:04.000000Z",
"updated_at": "2023-04-18T09:59:51.000000Z",
"deleted_at": null,
"is_deleting": false,
"tiers": [
{
"id": 69,
"user_id": 1,
"company_id": 1,
"buyer_id": 3,
"country_id": 1,
"product_id": 1,
"name": "Fake-accept 62",
"description": "Fake accept with delay",
"processing_class": "FakeBuyer",
"is_default": false,
"is_enabled": true,
"last_used_at": null,
"created_at": "2023-04-17T13:41:04.000000Z",
"updated_at": "2023-04-17T13:41:04.000000Z",
"deleted_at": null,
"is_deleting": false,
"options": []
},
{
"id": 70,
"user_id": 1,
"company_id": 1,
"buyer_id": 3,
"country_id": 1,
"product_id": 1,
"name": "Fake-accept 63",
"description": "Fake accept with delay",
"processing_class": "FakeBuyer",
"is_default": false,
"is_enabled": true,
"last_used_at": null,
"created_at": "2023-04-17T13:41:05.000000Z",
"updated_at": "2023-04-17T13:41:05.000000Z",
"deleted_at": null,
"is_deleting": false,
"options": [
{
"id": 764,
"user_id": 1,
"company_id": 1,
"buyer_tier_id": 70,
"name": "min_price",
"value": 2.5,
"description": null,
"cast": "float",
"type": "private",
"is_enabled": true,
"created_at": "2023-04-17T15:13:16.000000Z",
"updated_at": "2023-04-17T15:13:16.000000Z",
"deleted_at": null,
"type_formatted": "Private",
"is_deleting": false
}
]
},
{
"id": 71,
"user_id": 1,
"company_id": 1,
"buyer_id": 3,
"country_id": 1,
"product_id": 1,
"name": "Fake-accept 64",
"description": "Fake accept with delay",
"processing_class": "FakeBuyer",
"is_default": false,
"is_enabled": true,
"last_used_at": null,
"created_at": "2023-04-17T13:41:05.000000Z",
"updated_at": "2023-04-17T13:41:05.000000Z",
"deleted_at": null,
"is_deleting": false,
"options": [
{
"id": 765,
"user_id": 1,
"company_id": 1,
"buyer_tier_id": 71,
"name": "min_price",
"value": 5,
"description": null,
"cast": "float",
"type": "private",
"is_enabled": true,
"created_at": "2023-04-18T10:33:04.000000Z",
"updated_at": "2023-04-18T10:33:04.000000Z",
"deleted_at": null,
"type_formatted": "Private",
"is_deleting": false
}
]
},
{
"id": 72,
"user_id": 1,
"company_id": 1,
"buyer_id": 3,
"country_id": 1,
"product_id": 1,
"name": "Fake-accept 65",
"description": "Fake accept with delay",
"processing_class": "FakeBuyer",
"is_default": false,
"is_enabled": true,
"last_used_at": null,
"created_at": "2023-04-17T13:41:05.000000Z",
"updated_at": "2023-04-17T13:41:05.000000Z",
"deleted_at": null,
"is_deleting": false,
"options": []
}
]
}
]
}
}
You see that the buyer tier "Fake-accept 62" has been retrieved despite it having no options. For the ones that are retrieved, it should match the type of private.
Here's loads of attempts I've done:
$buyers = Buyer::with([
'tiers.options'
])->whereHas('tiers.options', function ($query) {
$query->where([
['type', 'private']
]);
})->get();
$buyers = Buyer::with([
'tiers.options'
])->withWhereHas('tiers.options', function ($query) {
$query->where('type', 'private');
})->get();
$buyers = Buyer::with('tiers.options', function ($query) {
$query->where('type', 'private')
})->get();
$buyers = Buyer::withWhereHas('tiers.options', function ($query) {
$query->where('type', 'private');
})->get();
They all continue to bring back tiers with no options despite the where clause.
答案1
得分: 3
Your query means you get buyers who have the type of tiers.options = private and get all tiers.options of those buyers.
如果您想要获取具有 tiers.options = private 类型的买家,并且只获取具有 type = private 的 tiers.options,您可以使用 withWhereHas:
$buyers = Buyer::withWhereHas('tiers', function($query) {
$query->withWhereHas('options', function ($query) {
$query->where([
['type', 'private']
]);
});
})->get();
英文:
Your query means you get buyers who have the type of tiers.options = private and get all tiers.options of those buyers
If you want to get buyers who have the type of tiers.options = private and also just get tiers.options that has type = private, you use withWhereHas:
$buyers = Buyer::withWhereHas('tiers', function($query) {
$query->withWhereHas('options', function ($query) {
$query->where([
['type', 'private']
]);
});
})->get();
答案2
得分: -1
尝试将 tiers
添加到 with
中,然后调用嵌套关系:
$buyers = Buyer::with([
'tiers', 'tiers.options'
])
英文:
try to add tiers
to with and then call the nested relation :
$buyers = Buyer::with([
'tiers','tiers.options'
])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论