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

PHP日历类同天多事件仅显示首个问题排查求助

PHP日历类同一日期多事件仅显示最早项的问题修复

我开发了一个用于网页展示的PHP日历类,目前日历可正常运行,但存在一个问题:当同一日期添加多个事件时,仅会显示最早创建的那个事件。已调试许久仍未定位原因,希望得到技术指导。

Calendar类代码

<?php

class Calendar {
    private $active_year, $active_month, $active_day;
    private $events = [];

    public function __construct($date = null) {
        $this->active_year = $date != null ? date('Y', strtotime($date)) : date('Y');
        $this->active_month = $date != null ? date('m', strtotime($date)) : date('m');
        $this->active_day = $date != null ? date('d', strtotime($date)) : date('d');
    }

    public function add_event($txt, $date, $days = 1, $color = '') {
        $color = $color ? ' ' . $color : $color;
        $this->events[] = [$txt, $date, $days, $color];
    }

    public function __toString() {
        $num_days = date('t', strtotime($this->active_day . '-' . $this->active_month . '-' . $this->active_year));
        $num_days_last_month = date('j', strtotime('last day of previous month', strtotime($this->active_day . '-' . $this->active_month . '-' . $this->active_year)));
        $days = [0 => 'Sun', 1 => 'Mon', 2 => 'Tue', 3 => 'Wed', 4 => 'Thu', 5 => 'Fri', 6 => 'Sat'];
        $first_day_of_week = array_search(date('D', strtotime($this->active_year . '-' . $this->active_month . '-1')), $days);
        $html = '<div class="calendar">';
        $html .= '<div class="header">';
        $html .= '<div class="month-year">';
        $html .= date('F Y', strtotime($this->active_year . '-' . $this->active_month . '-' . $this->active_day));
        $html .= '</div>';
        $html .= '</div>';
        $html .= '<div class="days">';
        foreach ($days as $day) {
            $html .= '
                <div class="day_name">
                    ' . $day . '
                </div>
            ';
        }
        for ($i = $first_day_of_week; $i > 0; $i--) {
            $html .= '
                <div class="day_num ignore">
                    ' . ($num_days_last_month-$i+1) . '
                </div>
            ';
        }
        for ($i = 1; $i <= $num_days; $i++) {
            $selected = '';
            if ($i == $this->active_day) {
                $selected = ' selected';
            }
            $html .= '<div class="day_num' . $selected . '">';
            $html .= '<span>' . $i . '</span>';
            foreach ($this->events as $event) {
                for ($d = 0; $d <= ($event[2]-1); $d++) {
                    if (date('y-m-d', strtotime($this->active_year . '-' . $this->active_month . '-' . $i . ' -' . $d . ' day')) == date('y-m-d', strtotime($event[1]))) {
                        $html .= '<div class="event' . $event[3] . '">';
                        $html .= $event[0];
                        $html .= '</div>';
                    }
                }
            }
            $html .= '</div>';
        }
        for ($i = 1; $i <= (42-$num_days-max($first_day_of_week, 0)); $i++) {
            $html .= '
                <div class="day_num ignore">
                    ' . $i . '
                </div>
            ';
        }
        $html .= '</div>';
        $html .= '</div>';
        return $html;
    }

}

?>

Calendar.css代码

.calendar {
    display: flex;
    flex-flow: column;
    overflow: scroll;
}
.calendar .header .month-year {
    font-size: 20px;
    font-weight: bold;
    color: #636e73;
    padding: 20px 0;
}
.header{
    height: 10%;
}
.calendar .days {
    display: flex;
    flex-flow: wrap;
    flex-wrap: wrap;
}
.calendar .days .day_name {
    width: calc(87.5% / 7);
    height: 5%;
    border-right: 1px solid #2c7aca;
    /* padding: 10px; */
    text-transform: uppercase;
    font-size: large;
    font-weight: bold;
    color: #818589;
    color: #fff;
    background-color: #448cd6;
}
.calendar .days .day_name:nth-child(7) {
    border: none;
}
.calendar .days .day_num {
    display: flex;
    flex-flow: column;
    width: calc(76.75% / 7);
    width: calc(87.5% / 7);
    border-right: 1px solid #e6e9ea;
    /* border-bottom: 1px solid #e6e9ea; */
    /* padding: 10px; */
    /* padding: 1%; */
    font-weight: bold;
    color: #7c878d;
    cursor: pointer;
    /* min-height: 100px; */
    min-height: 20%;
    /* min-height: 5%; */
    height: 5%;
    background-color: white;
}
.calendar .days .day_num span {
    display: inline-flex;
    width: 30px;
    width: 10%;
    font-size: 14px;
    font-size: small;
}
.calendar .days .day_num .event {
    margin-top: 10px;
    margin-bottom: 200%;
    font-weight: 500;
    font-size: 14px;
    padding: 3px 6px;
    border-radius: 4px;
    background-color: #f7c30d;
    color: #fff;
    word-wrap: break-word;
}
.calendar .days .day_num .event.green {
    background-color: #51ce57;
}
.calendar .days .day_num .event.blue {
    background-color: #518fce;
}
.calendar .days .day_num .event.red {
    background-color: #ce5151;
}
.calendar .days .day_num:nth-child(7n+1) {
    border-left: 1px solid #e6e9ea;
}
.calendar .days .day_num:hover {
    background-color: #fdfdfd;
    background-color: gainsboro;
}
.calendar .days .day_num.ignore {
    background-color: #fdfdfd;
    background-color: black;
    color: #ced2d4;
    cursor: inherit;
}
.calendar .days .day_num.selected {
    background-color: #f1f2f3;
    background-color: gainsboro;
    cursor: inherit;
}

问题原因及修复方案

问题并非出在PHP逻辑里,而是CSS样式导致的:.calendar .days .day_num .event中的margin-bottom: 200%;会让第一个事件占据容器内几乎所有可用空间,后续事件被挤出了可视区域,看起来像是只显示了最早的事件。

修复步骤:

  1. 移除.event样式中的margin-bottom: 200%;属性
  2. 可选:根据实际需求调整margin-top或添加max-height、overflow-y: auto来优化多事件的显示效果

修改后的.event样式示例:

.calendar .days .day_num .event {
    margin-top: 10px;
    font-weight: 500;
    font-size: 14px;
    padding: 3px 6px;
    border-radius: 4px;
    background-color: #f7c30d;
    color: #fff;
    word-wrap: break-word;
    /* 可选:如果事件过多,添加滚动条 */
    /* max-height: 60px; */
    /* overflow-y: auto; */
}

另外,PHP部分的事件循环逻辑可以优化(比如提前按日期分组事件,避免每天遍历所有事件),但这不是当前显示问题的核心。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:32:34