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 [1786 просмотров]

