I need to sort a collection from my database like this https://www.bodybuilding.com/store/listing.htm
I could write it, but I'd probably also lose the eloquent relationships which isn't ideal.
This feels like something Laravel something can do out of the box, or with very little logic.
Any suggestions?
Checkout the Laravel documentation https://laravel.com/docs/5.7/eloquent#retrieving-models
$listing = App\Store::where('first_letter', 'a')
->orderBy('name', 'desc')
->take(10)
->get();
If you need something more specific, you can always create Scopes
and use those in your eloquent models. https://laravel.com/docs/5.7/eloquent#query-scopes
Assuming a model called Categories
with a field name
and you need to group the categories by the first letter of their name. Each category with a first letter that is not an alphabetic character will be grouped under the '#' symbol:
$collection = Categories::get();
$grouped = $collection->groupBy(function ($item, $key) {
$letter = $item->name[0];
if (ctype_alpha($letter)) {
return $letter;
}
return '#';
});
mapToGroups
is what I was looking for. Here's my solution.
public function chunkByAlpha(Collection $collection)
{
return $collection->mapToGroups(function($item, $key) {
return ($this->isAlpha($item->name[0]) ? [strtoupper($item->name[0]) => $item] : ['#' => $item]);
});
}
public function isAlpha($toCheck)
{
return preg_match("/^[a-zA-Z]+$/", $toCheck);
}
Seems like an ordinary foreach()
would suffice
$ordered = [];
foreach ($items as $item) {
$key = ctype_alpha($item->attribute[0]) ? $item->attribute[0] : 'other';
$ordered[$item->attribute[0]][] = $item;
}
The above produces an assoc array with the letter as key - and put all none-alpha items in other