БлогNot. PHP: простой класс календаря с поддержкой вывода событий

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>&nbsp;</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 [732 просмотра]


теги: программирование css php дата

показать комментарии (3)