You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP日历代码中实现单日多个事件的显示

PHP日历单日多事件显示修复方案

问题根源

原代码通过mysqli_fetch_assoc($events)仅读取数据库返回的第一条事件记录,导致同一天的后续事件无法被加载和展示。

修复步骤

1. 预加载当月所有事件(性能优化)

避免在日期循环内逐天查询数据库,一次性获取当月所有事件并按日期分组:

// 在日期循环前添加,预加载当月事件
$monthEvents = [];
$eventsQuery = mysqli_query($connect, "SELECT id, title, day FROM `posts` WHERE SUBSTR(date,7,4)='$cYear' AND month='$cMonth'");
while ($eventRow = mysqli_fetch_assoc($eventsQuery)) {
    $eventDay = intval($eventRow['day']);
    if (!isset($monthEvents[$eventDay])) {
        $monthEvents[$eventDay] = [];
    }
    $monthEvents[$eventDay][] = $eventRow;
}

2. 修改日期循环内的事件读取逻辑

替换原单条事件读取代码,从预加载数组中获取当日所有事件:

// 替换原有的数据库查询及单条记录读取代码
$dailyEvents = isset($monthEvents[$d]) ? $monthEvents[$d] : [];
$hasEvents = !empty($dailyEvents);

3. 调整显示逻辑,支持多事件展示

修改单元格样式和内容输出,让单日多事件可见:

  • 调整单元格垂直对齐为顶部,增加内边距
  • 日期下方列出所有事件的短标题链接

完整修改后的代码

<?php
$cMonth = isset($_REQUEST["month"]) ? intval($_REQUEST["month"]) : date("m");
$cYear = isset($_REQUEST["year"]) ? intval($_REQUEST["year"]) : date("Y");
$prev_year = $cYear;
$prev_year2 = $cYear-1;
$next_year = $cYear;
$next_year2 = $cYear+1;
$prev_month = $cMonth-1;
$next_month = $cMonth+1;
 if ($cMonth == 12 ) {
    $next_month = 1;
    $next_year = $next_year2;
 } elseif ($cMonth == 1 ) {
    $prev_month = 12;
    $prev_year = $prev_year2;
}
$short_days = array('1'=>'Sun', '2'=>'Mon', '3'=>'Tue', '4'=>'Wed', '5'=>'Thu', '6'=>'Fri', '7'=>'Sat');
$day=intval(date('d'));
$endDate=date('t',mktime(0,0,0,$cMonth,$day,$cYear));

// 预加载当月所有事件,按日期分组
$monthEvents = [];
$eventsQuery = mysqli_query($connect, "SELECT id, title, day FROM `posts` WHERE SUBSTR(date,7,4)='$cYear' AND month='$cMonth'");
while ($eventRow = mysqli_fetch_assoc($eventsQuery)) {
    $eventDay = intval($eventRow['day']);
    if (!isset($monthEvents[$eventDay])) {
        $monthEvents[$eventDay] = [];
    }
    $monthEvents[$eventDay][] = $eventRow;
}

echo "<table width='100%' align='center' border='0' cellpadding='0' cellspacing='5'><tr bgcolor='white'>
";
echo "<td align='left'><a class='caldate3' href='".$_SERVER['PHP_SELF']."?month=$prev_month&amp;year=$prev_year' title='Previous Month'>&nbsp;<big>&laquo;&laquo;</big>&nbsp;Prev</a></td>
";
echo "<td align='center'><a class='mcaldate2' href='#' title='Current Month'>&nbsp;".date("F Y",strtotime($cYear."-".$cMonth."-01"))."&nbsp;</a></td>
";
echo "<td align='right'><a class='caldate3' href='".$_SERVER['PHP_SELF']."?month=$next_month&amp;year=$next_year' title='Next Month'>Next&nbsp;<big>&raquo;&raquo;</big>&nbsp;</a></td></tr>
";
echo "<tr><td colspan='3' height='5'></td>
";
echo "</tr></table>
";
echo "<table width='100%' align='center' border='0' cellpadding='0' cellspacing='0'><tr><td class='norm'>
";
echo "<table width='100%' align='center' border='0' cellpadding='2' cellspacing='1'><tr bgcolor='#000' height='20'>
";
    foreach ($short_days as $key=>$val) {
echo "<td width='14%' align='center'><span style='font-size:14px; color:#ffff00;'><b>".$val."</b></span></td>
";
        }
echo "</tr><tr>
";
$s=date('w', mktime (0,0,0,$cMonth,1,$cYear));
for ($ds=1; $ds<=$s; $ds++) {
echo "<td class='norm' height='20' align='center' valign='middle'></td>
";
    }
for ($d=1; $d<=$endDate; $d++) {
if (date('w',mktime (0,0,0,$cMonth,$d,$cYear)) == 0) {
    echo "</tr><tr>
";
    }

// 获取当日所有事件
$dailyEvents = isset($monthEvents[$d]) ? $monthEvents[$d] : [];
$hasEvents = !empty($dailyEvents);

// 确定单元格样式
if ($hasEvents) {
    echo "<td class='event' align='center' valign='top' style='padding:4px;'>";
} elseif ($d == $day && $cMonth == intval(date('m'))) {
    echo "<td class='today' align='center' valign='top' style='padding:4px;'>";
} else {
    echo "<td class='norm' align='center' valign='top' style='padding:4px;'>";
}

$dPadded = str_pad($d,2,'0',STR_PAD_LEFT);
// 输出日期数字
echo "<span class='date-number'>$dPadded</span><br>";

// 输出所有事件链接
if ($hasEvents) {
    foreach ($dailyEvents as $event) {
        // 截断标题避免过长
        $shortTitle = strlen($event['title']) > 12 ? substr($event['title'], 0, 12) . "..." : $event['title'];
        echo "<a class='event-link' href='post.php?id=" . $event['id'] . "' title='" . htmlspecialchars($event['title']) . "'>$shortTitle<br></a>";
    }
}

echo "</td>
";
if (date('w',mktime (0,0,0,$cMonth,$d,$cYear)) == 6) {
echo "</tr>";
    }
}
echo "</table></td></tr><tr><td height='8'></td>
";
echo "</tr></table>
";
echo "</td></tr></table>
";
?>

额外说明

  • 新增htmlspecialchars()处理事件标题,避免XSS注入风险
  • 调整单元格布局,优化多事件的展示空间
  • 预加载事件的方式减少了数据库查询次数,提升日历加载效率

内容的提问来源于stack exchange,提问作者veeger9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:18:13