我正在为我的应用程序构建搜索功能。为了简化事情: 有两个表:商店和订阅
每个商店可以有多个订阅记录,订阅具有字段expires_at
。现在,我假设如果存在订阅,并且商店的至少一项预订的expires_at date比now()大,则商店具有有效的订阅。
这是整个查询的条件之一。这是代码:
$shops = Shop::when($subscription, function($query, $subscription) {
$query->doesntHave('subscriptions')->orWhereHas('subscriptions', function($q) use ($subscription, $query) {
$query->where('expires_at', '<', now());
});
});
它不能按预期工作,因为如果shop具有三个相关的订阅,并且其中至少有一个已过期–则假定shop没有有效的订阅(即使已订阅)。
我需要在内部或其中实现一些嵌套函数,以便按expires_at desc排序,然后限制为1,然后再传递whereexpires_at子句,但是我不知道如何实现。
我宁愿坚持使用Eloquent Query Builder,而不是DB Facade或原始SQL。
基本上,这里没有回答的是相同的问题: https://laracasts.com/discuss/channels/eloquent/latest-record-from-relationship-in-wherehas?page=1
答案 0 :(得分:0)
尝试一下:
$shops = Shop::doesntHave('subscriptions')->orWhereHas('subscriptions', function ($query) {
$query->whereDate('expires_at', '<', now());
})->get();
答案 1 :(得分:0)
尝试:
$shops = Shop::WhereHas('subscriptions')->withCount('subscriptions as
active_subscriptions_count' => function ($query) {
$query->where('expires_at', '<', now());
}])->having('active_subscriptions_count', '>=', 3)->get();
答案 2 :(得分:0)
好吧,所以在尝试一些原始sql之后,我发现了:
$query->select('shops.*')
->leftJoin('subscriptions', 'shops.id', 'subscriptions.shop_id')
->whereNull('subscriptions.id')
->orWhere('subscriptions.expires_at', '<', now())
->where('subscriptions.id', function($q) {
$q->select('id')
->from('subscriptions')
->whereColumn('shop_id', 'shops.id')
->latest('expires_at')
->limit(1);
});
这不仅比where子句快,而且还提供了我所需的内容–仅考虑给定商店的“最高”订阅。