Search code examples
laraveleloquentlaravel-5.1php-carbon

Laravel Date comparison not working in Eloquent query


I do not understand why but following query return null resultset.

due_date is Carbon date and $now=Carbon:today();

$subQuery = BillTable::where('busi_id', $business->busi_id)
        ->where('due_date','>=',$now)
        ->where('due_date','<',$now->addMonth())
        ->get();

Also when I use whereBetween it doesn't work.

$subQuery = BillTable::where('busi_id', $business->busi_id)
        ->whereBetween('due_date',[$now, $now->addMonth()])
        ->get();

But when I just to greater than or lesser than it works

$subQuery = BillTable::where('busi_id', $business->busi_id)
        ->where('due_date','>',$now->addWeek())
        ->get();

What am I missing here?


Solution

  • The problem here is that you are using the same instance for both range limits. When you call addMonth you add the month to the instance stored in $now. The two examples below illustrate the issue:

    1. Using and modifying the same variable in two separate statements works as you'd expect:

    $now = Carbon::now();
    
    dump($now); // prints 2015-12-12 14:50:00.000000
    dump($now->addMonth); // prints 2016-01-12 14:50:00.000000
    

    2. Using the same variable and modifying it in the same statement that passes the values to a method, will work differently, because it will be evaluated before being passed to the method. Meaning that both parameters will be equal because they both contain the same instance from the $now variable, which after getting evaluated will contain the DateTime of one month from now.

    $now = Carbon::now();
    
    // Calling `addMonth` will change the value stored in `$now`
    dump($now, $now->addMonth());
    
    // The above statement prints two identical DateTime values a month from now:
    // 2016-01-12 14:50:00.000000 and 2016-01-12 14:50:00.000000
    

    This means that your current code was checking if the entries were due only exactly one month from now.


    To fix it you need to use two instances in two separate variables:

    $from = Carbon::now();
    $to = Carbon::now()->addMonth();
    
    $subQuery = BillTable::where('busi_id', $business->busi_id)
                         ->whereBetween('due_date',[$from, $to])
                         ->get();