Группировка событий по годам, месяцам, а затем распечатка для каждого - PHP и MySQL - PullRequest
0 голосов
/ 24 марта 2012

У меня есть таблица MySQL, содержащая список событий, которые я пытаюсь отобразить так (не точное форматирование):

2011

Январь

  • Январь Событие 1
  • Январь Событие 2
  • Январь Событие 3

2012

Март

  • Мар Событие 1
  • Мар Событие 2

Я наконец смог выполнить это, используя приведенный ниже PHP, но я знаю , что должен быть лучший путь. Как вы увидите, есть два вложенных for each оператора. Столбец dateStart представляет собой DATE.

$fetchEvents = $contentDB->query("SELECT id, title, description, dateStart, dateEnd, timeStart, timeEnd, 
YEAR(dateStart) AS year, MONTH(dateStart) AS month, MONTHNAME(dateStart) AS monthName
 FROM events_general ORDER BY dateStart");
while ($event = $fetchEvents->fetch())
{
    $title = $event['title'];
    $description = $event['description'];
    $dateStart = $event['dateStart'];
    $month = $event['monthName'];
    $year = $event['year'];
    $events[$year][$month][] = array(
        'title' => $title,
        'description' => $description,
        'dateStart' => $dateStart);
}
foreach ($events as $year => $month)
{
    echo "<p><strong>$year</strong>\n";
    foreach ($month as $monthListing => $eventListing)
    {
        echo "
        <p>$monthListing</p>\n
        <div class=\"accordion\">\n
        ";
        foreach ($eventListing as $event)
        {
            $title = $event['title'];
            $description = $event['description'];
            $dateStart = $event['dateStart'];
            echo "
            <h3><a href=\"#\">$title - $dateStart</a></h3>\n
            <div>\n
            $description \n
            </div>\n
            ";
        }
        echo "</div>\n";
    }
}

Ответы [ 2 ]

3 голосов
/ 24 марта 2012

Это будет сделано за одну итерацию, но вам нужно будет поиграть с тем, куда поместить закрывающий </div> для аккордеона -

$fetchEvents = $contentDB->query("SELECT id, title, description, dateStart, dateEnd, timeStart, timeEnd, 
YEAR(dateStart) AS year, MONTH(dateStart) AS month, MONTHNAME(dateStart) AS monthName
 FROM events_general ORDER BY dateStart");

$prevYear = '';
$prevMonth = '';

while ($event = $fetchEvents->fetch())
{
    $title = $event['title'];
    $description = $event['description'];
    $dateStart = $event['dateStart'];
    $month = $event['monthName'];
    $year = $event['year'];

    if ($year <> $prevYear) {
        // if a new year we definitely need to close the previous accordion div
        // unless it's the first iteration
        if ($prevMonth) {
            echo '</div><!-- close accordion div -->';
        }
        echo "<p><strong>$year</strong>\n";
    }
    if ($year <> $prevYear || $month <> $prevMonth) {
        // if new month but not new year close accordion
        if ($year == $prevYear) {
            echo '</div><!-- close accordion div -->';
        }
        echo "<p>$monthListing</p>\n";
        echo "<div class=\"accordion\">\n";
    }

    echo "<h3><a href=\"#\">$title - $dateStart</a></h3>\n<div>\n$description \n</div>\n";

    $prevYear = $year;
    $prevMonth = $month;
}
// add final closing div here
echo '</div><!-- close accordion div -->';
0 голосов
/ 24 марта 2012

Вот запрос, НЕМНОГО измененный. У меня есть внутренний запрос, который просто захватывает год, месяц и дату последнего события в год / месяц. Затем, присоединившись к этому, я добавил проверку IF (), что если дата начала совпадает с датой запроса «MaxPerMthYr», то установите флаг в 1, в противном случае оставьте его равным нулю. Это может не работать идеально, если у вас есть несколько событий в одну и ту же дату. Если это так, то нужно будет сделать другую модификацию, но она выполнима, чтобы гарантировать правильную запись. Остальная часть вашего PHP-кода должна работать, но теперь у вас будет флаг, который вы искали.

SELECT 
      id, 
      title, 
      description, 
      dateStart, 
      dateEnd, 
      timeStart, 
      timeEnd, 
      YEAR(dateStart) AS year, 
      MONTH(dateStart) AS month, 
      MONTHNAME(dateStart) AS monthName,
      if( dateStart = MaxPerMthYr.LastDatePerGroup, 1, 0 ) as LastEntryPerGroup
    FROM 
       events_general,
          JOIN ( select YEAR(dateStart) AS perYear, 
                        MONTH(dateStart) AS perMonth, 
                        max( dateStart ) as LastDatePerGroup
                    from
                       events_general 
                    group by
                       YEAR(dateStart) AS perYear, 
                       MONTH(dateStart) AS perMonth ) MaxPerMthYr
           ON Year( Events_General.dateStart ) = MaxPerMthYr.perYear
             AND Month( Events_General.dateStart ) = MaxPerMthYr.perMonth
    ORDER BY 
       dateStart
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...