Laravel whereHas 行为异常
Laravel whereHas behaving unexpectedly
我在 Laravel 5.6 应用程序中设置了以下关系。
Purchase belongs to many Invoice
Invoice belongs to many Purchase
Invoice belongs to many Payment
Payment belongs to many Invoice
这些关系是使用数据透视表建立的。
我想查找仅 次购买,通过发票,付款为 0。
在我的测试中,我有 一次 次购买,我已为该次购买附上 两张 发票,并且我已附上 one 支付给每张发票。一笔付款的金额为 100,另一笔付款的金额为 0。
为了让我的测试通过,查询应该 return 没有结果,但是,它没有这样做,它一直在 return 我创建的购买。
这是我写的查询:
Purchase::whereHas('invoices.payments', function ($q) {
return $q->where('amount', '<=', 0);
})->get();
我也试过:
Purchase::whereDoesntHave('invoices.payments', function ($q) {
return $q->where('amount', '>', 0);
})->get();
我是不是做错了什么?我是不是误解了 WhereHas 的功能?
非常感谢任何帮助,谢谢。
我想,你应该使用这两种方法。
Purchase::whereHas('invoices.payments', function ($q) {
return $q->where('amount', 0);
})
->whereDoesntHave('invoices.payments', function ($q) {
return $q->where('amount', '>', 0);
})
->get();
whereHas()
接受所有支付金额 = 0 的购买,whereDoesntHave()
丢弃支付金额 > 0 的购买。
也许是我没有完全理解您的要求/这里的问题,但这就是我想我理解的...
您创建了 1 个 Purchase
。
它有 2 Invoice
s。
每个 Invoice
有 1 Payment
(100 个中的 1 个,0 个中的 1 个 <- 技术上不是付款)。
在你的问题中你说
I want to find only purchases that have, via invoices, payments that
are 0.
但是你抱怨你得到了一个结果......当你DO以零付款购买时。
为了使测试更复杂一些 "real",我会创建许多 Purchase
s,其中包含许多 Invoice
s 和 Payment
s 等,以真正感受怎么回事
更新
您是否考虑过 'hasManyThrough' 购买模型与付款的关系?像这样
public function payment()
{
return $this->hasManyThrough(Payment::class, Invoice::class);
}
那么也许您可以执行此查询。
Purchase::whereDoesntHave('payment')->get();
您的第二种方法是正确的,但是 whereDoesntHave()
不能正确处理 Laravel 5.6 中的嵌套关系。此错误已 fixed Laravel 5.7。
您可以使用此解决方法:
Purchase::whereDoesntHave('invoices', function ($q) {
$q->whereHas('payments', function ($q) {
$q->where('amount', '>', 0);
});
})->get();
我在 Laravel 5.6 应用程序中设置了以下关系。
Purchase belongs to many Invoice
Invoice belongs to many Purchase
Invoice belongs to many Payment
Payment belongs to many Invoice
这些关系是使用数据透视表建立的。
我想查找仅 次购买,通过发票,付款为 0。
在我的测试中,我有 一次 次购买,我已为该次购买附上 两张 发票,并且我已附上 one 支付给每张发票。一笔付款的金额为 100,另一笔付款的金额为 0。
为了让我的测试通过,查询应该 return 没有结果,但是,它没有这样做,它一直在 return 我创建的购买。
这是我写的查询:
Purchase::whereHas('invoices.payments', function ($q) {
return $q->where('amount', '<=', 0);
})->get();
我也试过:
Purchase::whereDoesntHave('invoices.payments', function ($q) {
return $q->where('amount', '>', 0);
})->get();
我是不是做错了什么?我是不是误解了 WhereHas 的功能?
非常感谢任何帮助,谢谢。
我想,你应该使用这两种方法。
Purchase::whereHas('invoices.payments', function ($q) {
return $q->where('amount', 0);
})
->whereDoesntHave('invoices.payments', function ($q) {
return $q->where('amount', '>', 0);
})
->get();
whereHas()
接受所有支付金额 = 0 的购买,whereDoesntHave()
丢弃支付金额 > 0 的购买。
也许是我没有完全理解您的要求/这里的问题,但这就是我想我理解的...
您创建了 1 个 Purchase
。
它有 2 Invoice
s。
每个 Invoice
有 1 Payment
(100 个中的 1 个,0 个中的 1 个 <- 技术上不是付款)。
在你的问题中你说
I want to find only purchases that have, via invoices, payments that are 0.
但是你抱怨你得到了一个结果......当你DO以零付款购买时。
为了使测试更复杂一些 "real",我会创建许多 Purchase
s,其中包含许多 Invoice
s 和 Payment
s 等,以真正感受怎么回事
更新
您是否考虑过 'hasManyThrough' 购买模型与付款的关系?像这样
public function payment()
{
return $this->hasManyThrough(Payment::class, Invoice::class);
}
那么也许您可以执行此查询。
Purchase::whereDoesntHave('payment')->get();
您的第二种方法是正确的,但是 whereDoesntHave()
不能正确处理 Laravel 5.6 中的嵌套关系。此错误已 fixed Laravel 5.7。
您可以使用此解决方法:
Purchase::whereDoesntHave('invoices', function ($q) {
$q->whereHas('payments', function ($q) {
$q->where('amount', '>', 0);
});
})->get();