Я создаю небольшое приложение Laravel, в котором я хочу отображать определенные выпуски, сгруппированные по месяцам. Что-то вроде этого:
January
11.1 - blabla
more blablabla the same day
15.1 - blablabla
February
05.2 - blabla
etc...
Итак, в своем контроллере я просто делаю это:
public function index() {
$releases = Release::orderBy('release_date', 'asc')->get();
return view('pages.index')->with('releases', $releases);
}
И в моем файле просмотра лезвия я просматриваю данные:
@foreach ($releases as $release)
<div>
<p>
<span>{{ \Carbon\Carbon::parse($release->release_date)->format('d. M')}}</span>
<span>{{$release->artist}} - {{$release->album_title}} </span>
</p>
</div>
@endforeach
Это дает мне правильные данные, например, список записей БД, но, как упоминалось ранее, я хочу сгруппировать их по месяцам и дополнительно добавить заголовок для каждого месяца. Как я могу этого добиться?
Я использую Laravel 5.5, если это важно ...






UNION ALL - лучший способ сгруппировать данные заголовка и даты по месяцам.
Вы можете использовать метод Collection :: groupBy () следующим образом:
$releases->groupBy(function(Release $release) {
return $release->release_date->format('F');
});
Теперь $ релизы - это Коллекция с названием месяца в качестве ключа и Коллекция (массив релизов) в качестве значения, подобного этому:
[
"January" => Collection{Release, Release, Release},
"February" => Collection{Release, Release, Release},
...
]
Не забывай годы;)
Если вы используете метод -> get () -> groupBy ('release_date'), он возвращает объекты по дате.
Например;
public function index() {
$releases = Release::orderBy('release_date', 'asc')->get()->groupBy('release_date');
return view('pages.index')->with('releases', $releases);
}
Думаю решу твою проблему.
public function index() {
$releases = Release::orderBy('release_date', 'asc')
->get()->groupBy('release_date.month');
return view('pages.index')->with('releases_groups', $releases);
}
@foreach ($releases_groups as $month => $releases_group)
// just place group info here...
@foreach ($releases_group as $release)
<div>
<p>
<span>{{ \Carbon\Carbon::parse($release->release_date)->format('d. M')}}</span>
<span>{{$release->artist}} - {{$release->album_title}} </span>
</p>
</div>
@endforeach
@endforeach
Попробуй это.
хм, я получаю Column not found, когда пробую это: - /
Починил, поставил ->groupBy('release_date.month') после get(), и все будет хорошо.
ах, я вижу, но хм ... Я не могу понять название месяца из этого ...: s
Да, я редактировал код, ключ коллекции - month, и это целое число от 1~12, но я не знаю, подходит ли вам этот формат.
Все доступные форматы: month, localeMonth, shortLocaleMonth, englishMonth, shortEnglishMonth, вы можете попробовать и посмотреть, какой вы хотите
Итак, как мне тогда получить информацию о группе?
@foreach ($releases_groups as $month => $releases_group), $month пока единственная информация о группе, хм, этого мало?
ах, плохо, я только что это увидел :-) Так что теперь мне просто нужно сравнить целочисленное значение и вернуть правильную строку, например 1 = январь, 2 = февраль и т. д.?
Вам не нужно этого делать, вместо этого используйте другой формат, например, ->groupBy('release_date.englishMonth'), $month будет «Январь», «Февраль» и т. д. Все доступные форматы месяцев были перечислены ранее.
Посмотрев на другие ответы, вы должны знать одну важную вещь: groupBy используется для группировки полученных вами результатов. Это означает, что если вы используете paginate вместо get, тот же месяц реальной жизни может быть неправильно сгруппирован.
Я предлагаю заставить ваш контроллер выполнять больше работы:
public function index() {
// Here we get a distinct list of dates in your format
$releaseDates = Release::Selectraw('date_format(date(release_date),"%d.%m") as Date')->distinct()->get();
// For each date we now get the elements for each date and put them as an array entry in to the date under a 'data' section
foreach($releaseDates as $releaseDate){
$releaseDate['data'] = Release::whereraw('date_format(date(release_date),"%d.%m") = '.$releaseDate->Date)->get();
}
// Pass the data to the view as before but with new name
return view('pages.index')->with('releaseDates', $releaseDates );
}
Тогда, на ваш взгляд:
// For each release date first
@foreach ($releaseDates as $releaseDate)
<div>
<p>
//Print out the date as requested
<span>{{ \Carbon\Carbon::parse($releaseDate->Date)->format('d. M')}}</span>
// Now loop through each record nested as an array inside the date
@foreach($releaseDate['data'] as $data)
<span>{{$data->artist}} - {{$data->album_title}} </span>
<br>
@endforeach
</p>
</div>
@endforeach
Теперь у каждой записи одна и та же дата :-)
@ ST80 Я добавил несколько комментариев, обратите внимание на второй цикл foreach в вашем представлении лезвия, который необходим для извлечения записей под каждой датой.
А что насчет этого (в вашем контроллере)?
$groupedReleases = null;
foreach ($releases as $release) {
$date = $release->release_date->format('your desired format');
$groupedReleases[$date][] = $release;
}
return $groupedReleases;
Сделать это можно так:
Таблица: релизы
id | released_at | bla_details | month_header_id
Таблица: month_headers
id | month(specific length int) | year(specific length int) | header
Модель: Release.php
public function month_header()
{
return $this->belongsTo('App\Models\Month');
}
Модель: MonthHeader.php
public function releases()
{
return $this->hasMany('App\Models\Release');
}
Помощник: getMonthName ($ integer)
Контроллер: TempController.php
public function temp()
{
$response['month_headers'] = MonthHeader::all();
return view('tempView', $response);
}
Просмотр лезвия: tempView.blade.php
@foreach($month_headers as $header)
{{getMonthName($header->month)." (".$header->header.")"}}
<ul>
@foreach($month_headers->releases() as $release)
<li>{{date('d.m', strtotime($release->released_at))." - ".$release->bla_details}}</li>
@endforeach
</ul>
@endforeach
Просмотр вывода
Январь (заголовок января)
Февраль (заголовок февраля)
и т.д...
Пояснение добавлено.
Тоже очень красивое решение! :-)
See the below select function with raw query where i added "Month Name" and "month number" for your reference.Please check the output.Hope this will help you
$releases = Release::select(DB::raw('some_field, MONTHNAME(release_date) as month_name, MONTHNAME(release_date) as month'))
->orderBy('release_date', 'asc')->get();
You may use GroupBy if you are sure that there is not more than one release on same date.
$releaseArray=[];
if (!empty($releases)) {
foreach($releases as $release){
$releaseArray[$release->month][] = $release;
}
}
print_r($releaseArray);
Теперь вы можете передать $ releaseArray в представление и выполнить итерацию для выпусков, сгруппированных по месяцам.
Ключ
groupBy('release_date.month')