laravel 基于ORM的 orWhere 使用技巧

虽然laravel 支持链式 orWhere ,但是如果查询条件较多的时候,直接链式orWhere的使用需要通过 闭包函数来实现

Posted by 昆山吴彦祖 on 2019.07.05

案例1

现在要在   优惠券表 'coupons' 中获取所有 

状态 'STATUS' = 1,  且

有效期 'valid’ = 1(永久有效)   或者 结束日期 'end_at'>= 今天

的 所有优惠券 ,给用户去领取

如果用SQL语句的话,就是:

select * from 'coupons' where `status`=1 and (`valid` =1 or `end_at`>= '2019-7-5').


如果要用laravel的ORM链式检索的话,我们会理所当然的用:

Coupon::where('status',1)->where('valid',1)->orWhere('end_at','>=','2019-7-5')->get();


结果检索出来的数据当然是不对的,上面的orm解析的语句是:

select * from 'coupons' where `status`=1 and `valid` =1 or `end_at`>= '2019-7-5'

等同于

select * from 'coupons' where (`status`=1 and `valid` =1) or `end_at`>= '2019-7-5'


解决办法

Coupon::where('status',1)->where(function ($query){
    $query->where('valid','!=',2)->orWhere('end_at','>=',now()->toDateString());
})->get();

通过闭包函数作为where的参数来实现括号的功能


案例2

现在要在   个人优惠券表 'customerCoupons' 中获取所有 

状态 'STATUS' = 1,  且

用户id 'customer_id' = user_id, 且

有效期开始日期 'start_at' =null  或  'start_at' <= 今天, 且

有效期开始日期 'end_at' =null  或  'end_at'>= 今天

的 所有 当前用户可用优惠券

如果用SQL语句的话,就是:

select * from `customerCoupons` where `status`=1 and `customer_id`= 用户id and (`start_at` is null or `start_at`<= '2019-7-5')  and (`end_at` is null or `end_at`>= '2019-7-5')


ORM链式表达式

CustomerCoupon::where('customer_id',$request->customer_id)->where('status',1)->where(function ($query){
    $query->where('start_at',null)->orWhere('start_at','<=',now()->toDateString());
})->where(function ($query){
    $query->where('end_at',null)->orWhere('end_at','>=',now()->toDateString());
})->get();


orm