PHP: простой класс календаря с поддержкой вывода событий
Когда реального будущего нет, нужно программировать календари, это уж в любом случае полезней, чем читать сочинённые в КГБ "прогнозы Ванги" или продолжать не получать ответов на свои вопросы. Напишем небольшой класс календаря, который:
- будет гибко себя вести в окнах разного размера (скрин ниже);
- сможет выводить календарь на месяц, заданное количество месяцев, год или заданное количество лет;
- всё оформление будет "держать" в CSS-классах с однотипными префиксами имён, например,
calendar-*****
; - сможет получать аргументом массив дат с элементами вида
'дата' => 'событие'
и выводить информацию о событии во всплывающем popup-окне по наведению мыши. Окна тоже желательно создать просто стилем CSS; - при этом даты могут быть, по меньшей мере, видов ДД.ММ.ГГГГ (однократное событие), ДД.ММ (событие повторяется каждый год), ДД (событие повторяется каждый месяц);
- разные виды событий не должны "мешать" друг другу и уметь выводиться вместе (например, для событий на даты "21.09" и "21.09.2022").
Скрипты проверялись на локальном сервере XAMPP с PHP 8.X. Вот код класса calendar.php
:
<?php class Calendar { public static function getMonth($month, $year, $events = []) { //на месяц $months = [ 1 => 'Январь', 2 => 'Февраль', 3 => 'Март', 4 => 'Апрель', 5 => 'Май', 6 => 'Июнь', 7 => 'Июль', 8 => 'Август', 9 => 'Сентябрь', 10 => 'Октябрь', 11 => 'Ноябрь', 12 => 'Декабрь' ]; $month = intval($month); $out = "\n".' <div class="calendar-item"> <div class="calendar-head">' . $months[$month] . ' ' . $year . '</div> <table> <tr> <th>Пн</th> <th>Вт</th> <th>Ср</th> <th>Чт</th> <th>Пт</th> <th>Сб</th> <th>Вс</th> </tr>'."\n"; $day_week = date('N', mktime(0, 0, 0, $month, 1, $year)) - 1; $out.= ' <tr>'."\n"; for ($x = 0; $x < $day_week; $x++) { $out.= ' <td> </td>'."\n"; } $days_counter = 0; $days_month = date('t', mktime(0, 0, 0, $month, 1, $year)); for ($day = 1; $day <= $days_month; $day++) { if (date('j.n.Y') == $day . '.' . $month . '.' . $year) $class = ' today'; elseif (time() > strtotime($day . '.' . $month . '.' . $year)) $class = ' past'; else $class = ''; $event_show = false; $event_text = []; if (!empty($events)) { foreach ($events as $date => $text) { $date = explode('.', $date); if (count($date) == 3) { $y = explode(' ', $date[2]); if (count($y) == 2) $date[2] = $y[0]; if ($day == intval($date[0]) && $month == intval($date[1]) && $year == $date[2]) { $event_show = true; $event_text[] = $text; } } elseif (count($date) == 2) { if ($day == intval($date[0]) && $month == intval($date[1])) { $event_show = true; $event_text[] = $text; } } elseif ($day == intval($date[0])) { $event_show = true; $event_text[] = $text; } } } if ($event_show) { $out.= ' <td class="calendar-day' . $class . ' event">' . $day."\n"; if (!empty($event_text)) { $out.= ' <div class="calendar-popup">' . implode('<br>', $event_text) . '</div>'."\n"; } $out.= ' </td>'."\n"; } else { $out.= ' <td class="calendar-day' . $class . '">' . $day . '</td>'."\n"; } if ($day_week == 6) { $out.= ' </tr>'."\n"; if (($days_counter + 1) != $days_month) $out.= ' <tr>'."\n"; $day_week = -1; } $day_week++; $days_counter++; } $out .= " </tr>\n </table>\n</div>"; return $out; } public static function getInterval($start, $end, $events = []) { //на период $curr = explode('.', $start); $curr[0] = intval($curr[0]); $end = explode('.', $end); $end[0] = intval($end[0]); $begin = true; $out = '<div class="calendar-wrapper">'."\n"; do { $out .= self::getMonth($curr[0], $curr[1], $events); if ($curr[0] == $end[0] && $curr[1] == $end[1]) $begin = false; $curr[0]++; if ($curr[0] == 13) { $curr[0] = 1; $curr[1]++; } } while ($begin == true); $out .= "\n".'</div>'."\n"; return $out; } } ?>
Файл index.php
может находиться в той же папке и быть, например, таким (основные действия и способы вызова класса показаны комментариями в листинге):
<!DOCTYPE html> <html lang="ru"> <head> <title>Event Calendar</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <?php require_once('calendar.php'); //Подключить класс календаря $events = [ //Создать или прочитать из БД массив событий '24.02.2022' => 'Невойна', //выведется только в 2022-м '21.09.2022' => 'Немогилизация', '01.01' => 'Новый год', //выведется каждый год '21.09' => '21 сентября', '28' => '28 число' //выведется каждый месяц ]; //На текущий год: echo Calendar::getInterval(date('01.Y'), date('12.Y'), $events); //Можно вместо этого раскоммментировать другие варианты вызова: //На фиксированный интервал январь - октябрь 2022: //echo Calendar::getInterval(date('01.2022'), date('10.2022'), $events); //Только на текущий месяц и без событий: //echo Calendar::getMonth(date('n'), date('Y')); //На год вперёд от текущего месяца: //echo Calendar::getInterval(date('n.Y'), date('n.Y', strtotime('+11 month')), $events); //На 10 лет вперёд от января текущего года: //echo Calendar::getInterval(date('01.Y'), date('01.Y', strtotime('+10 year')), $events); ?> </body> </html>
Стиль style.css
можно получить по прямой ссылке.
Скрипт EventCalendar в работе, тестовые события случайны (новое окно/вкладка)

Скрипт в окнах разного размера
28.09.2022, 01:23 [1071 просмотр]