Laravel Collection Date comparison
Asked Answered
R

1

18

Alright so I have been looking for hours for an answer but can't seem to find one. I have an array of "orders" all for different dates. I get all of the orders for this week, this should not be an issue, then I want to a tab for each day of the week.

What I have tried so far is this:

$dinnerOrders->where('date','>',$date)->where('date','<', $date->endOfDay())->sortBy('created_at');

Where $date is :

$dt = Carbon\Carbon::create()->startOfWeek();
Carbon\Carbon::setTestNow($dt);
$date = new Carbon\Carbon('this ' . $day);

And $dinnerOrders are get by:

$dinnerOrders = collect([]);
foreach($restaurant->dinners as $dinner) {
    foreach($dinner->orders as $order) {
        $dinnerOrders[$order->id] = $order;
    }
 }

The dates seem correct and it words in sql. Is this not working because $dinnerOrders is a collection?

What I'm getting is nothing, i.e an empty set, despite it working in mysql terminal.

So what I'm asking is perhaps, can you do a date comparison on a collection? If so, how?

Ruddie answered 19/11, 2015 at 14:22 Comment(4)
You might not be building the entire query correctly, and you only posted a portion which looks fine. So instead of using get() to retrieve your results, use toSql() and that will return a string with the SQL query that is being built and run by the Query Builder. Does that match what you are running manually?Coenosarc
I would check what query is executing. Put this code after executing query and check sql beding executed: dd(DB::getQueryLog()) (to use DB you should import it: use Illuminate\Support\Facades\DB;)Destiny
@Coenosarc toSql() isn't working since $dinnerOrders are a collection which was already retrieved by sql, sorry should have been more clear. Have updated original question.Ruddie
My mistake, you were clear that it's a collection from the original question, I just missed that fact.Coenosarc
M
27

Note: This answer is specific to Laravel <= 5.2. Laravel 5.3 updated the where() method on the Collection to match the query builder, so it now accepts an operator.


As you state in your question, $dinnerOrders is a Collection, not a query. The where() method on the Collection works a little differently.

For Collections, the where() method does not accept an operator. It only does equality comparisons. The first parameter is the key, the second is the value, and the third is a boolean to flag a loose comparison (==) vs a strict comparison (===).

What you're looking for is the filter() method. You pass in a Closure that does your date comparison. If the Closure returns true, the item stays in the Collection. If it returns false, the item is removed from the Collection. Something like this (just an example, the logic may need to be tweaked):

$dinnerOrders = $dinnerOrders->filter(function ($item) use ($date) {
    return (data_get($item, 'date') > $date) && (data_get($item, 'date') < $date->endOfDay());
});

Post Question Edit

Based on the code provided in your edit, I'm guessing that a restaurant hasMany dinners, and a dinner hasMany orders. If this is correct, you can setup a relationship stating that a restaurant hasMany orders through dinners:

Restaurant.php:

public function orders() {
    // restaurant has many orders through dinners
    $this->hasManyThrough('App\Order', 'App\Dinner');
}

With this relationship setup, you could then get your information using the query builder:

$dinnerOrders = $restaurant->orders()->where('date','>',$date)->where('date','<', $date->endOfDay())->get();
Merissa answered 19/11, 2015 at 15:12 Comment(2)
Thank you! This worked perfectly, only problem was with my $date being end of day for some reason so I just switch $date in the function to $date->startOfDay()Ruddie
@user3032753 Yeah, I didn't test all the carbon comparison stuff, so I figured you might need to change the code a little, but I wanted to get the idea across. I'm glad it helped.Merissa

© 2022 - 2024 — McMap. All rights reserved.