按年份,月份和每个列表分组事件 - PHP和MySQL

时间:2012-03-23 21:44:58

标签: php mysql date

我有一个MySQL表,其中包含我试图显示的事件列表(不是精确格式化):

2011

一月

  • Jan Event 1
  • Jan Event 2
  • Jan Event 3

2012

三月

  • 3月活动1
  • 3月活动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 个答案:

答案 0 :(得分:3)

这将在一次迭代中完成,但你需要摆弄手风琴的结束</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 -->';

答案 1 :(得分:0)

这是稍微修改过的查询。我有一个内部查询,只能抓住每年/每月的年,月和最后一个事件日期。然后,通过加入,我添加了IF()检查,如果日期开始匹配预先查询“MaxPerMthYr”的那个,则将标志设置为1,否则,将其保留为零。如果您在同一天有多个事件,这可能无法正常工作。如果是这种情况,则需要进行另一次修改,但IS可以保证正确输入。其余的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