Laravel whereHas 只返回符合条件的模型。

huangapple go评论54阅读模式
英文:

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'
])

huangapple
  • 本文由 发表于 2023年4月19日 15:21:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76051734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定