Hi guys, thank you very much for your contribution. Sorry, I have put too much on the fire with $entries and so on.
To summarize the main problem, here's what happened: originally, I used MYSQL datetime functions massively in order to pre-select aggregates at the database level before processing the resulting entries later with collection methods. However, one day I was told that I would have to deploy the project on Windows Server with Microsoft SQL Server - 70% of the tests obviously failed, since I had used a ton of MYSQL-specific functions.
The more I think about it, the more I am convinced that pre-aggregating the entries at the database level isn't worth the loss of compatibility between DBMS and sounds like premature optimization. As you suggested, burlresearch, I am trying to become Eloquent and Collection's friend, and migrate the logic to that level. ;)
Here is something I came up with today, still has a bit too many foreachs, but at least doesn't add another database query. In this example, the method exports the entries as an array for a CSV file creator. Instead of having two different fields for date and hour, I kinda concatenated them together in the field 'start_time'.
public function scopeExport($builder)
{
$entries = $builder->oldest('visited_at')->get()
->groupBy(function ($item) {
return $item->visited_at->format('Y-m-d H:00:00');
})->map(function ($collection) {
return $collection->groupBy('patronCategory.name');
});
/**
* At this point, we've got a structure like:
* [
* '2017-02-12 10:00:00 => [
* 'FooCategory' => [
* Record1,
* Record2,
* Record3
* ],
* 'BarCategory' => [
* Record1,
* Record2
* ],
* ]
* ]
*/
$visits = [];
foreach ($entries as $datetime => $categories) {
foreach ($categories as $category => $records) {
$visits[] = [
'start_time' => $datetime,
'category' => $category,
'visits' => count($records)
];
}
}
return $visits;
}
As a side note, I am still convinced that something like selectDate('created_at') or selectHour('created_at') would be a nice abstraction in the query builder.