Создание календаря средствами PHP и CSS

27-08-2010

Сейчас мы попробуем сделать простенький календарь для сайта или еще для чего нибудь, не знаю ). Календарь будет не совсем простым можно будет переключатся между месяцами, а текущий день будет выделен среди других дней также другим цветом(красным) будут выделены выходные, правда только воскресения субботы я чето не стал выделять, ну это не важно.
Так как календарь будет переключатся между месяцами мы должны это как то передавать например методом GET т.е. через url адрес. Также напишем для календаря простенькие CSS чтоб можно было смотреть)) так это календарь удобней всего оформить его в виде таблицы. Внешне календарь будет выглядеть примерно так:

cakendar witht-css

На PHP мы создадим две переменные $calendar_head и $calendar_body соответственно в $calendar_head мы будем записывать html код верхней части календаря т.е. название месяца, дни недели и две ссылки по краям для выбора месяца. А в $calendar_body будем сохранять остальной код то есть таблицу дней недели. Ниже на скрине показано:

Теперь рассмотрим сам php код:

// проверяем передали ли нам месяц и год
if(isset($_GET["ym"])){

	$year  = (int)substr($_GET["ym"], 0, 4);
	$month = (int)substr($_GET["ym"], 4, 2);

}
else{ // иначе выводить текущие месяц и год

	$month = date("m", mktime(0,0,0,date('m'),1,date('Y')));
	$year  = date("Y", mktime(0,0,0,date('m'),1,date('Y')));

}

$skip          = date("w", mktime(0,0,0,$month,1,$year)) - 1; // узнаем номер дня недели
if($skip < 0){
	$skip = 6;
}
$daysInMonth   = date("t", mktime(0,0,0,$month,1,$year));	// узнаем число дней в месяце
$calendar_head = '';	// обнуляем calendar head
$calendar_body = '';	// обнуляем calendar boday
$day = 1;	// для цикла далее будем увеличивать значение

for($i = 0; $i < 6; $i++){ // Внешний цикл для недель 6 с неполыми

	$calendar_body .= '<tr>';	// открываем тэг строки
	for($j = 0; $j < 7; $j++){	// Внутренний цикл для дней недели

		if(($skip > 0)or($day > $daysInMonth)){ // выводим пустые ячейки до 1 го дня ип после полного количства дней

			$calendar_body .= '<td class="none"> </td>';
			$skip--;

		}
		else{

			if($j == 0)	// если воскресенье то омечаем выходной
				$calendar_body .= '<td class="holiday">'.$day.'</td>';
			else{	// в противном случае просто выводим день в ячейке
				if ((date(j)==$day)&&(date(m)==$month)&&(date(Y)==$year)){//проверяем на текущий день
					$calendar_body .= '<td class="today">'.$day.'</td>';
				}
				else{
					$calendar_body .= '<td class="day">'.$day.'</td>';
				   }
				 }
			$day++; // увеличиваем $day
		}

	}
	$calendar_body .= '</tr>'; // закрываем тэг строки
}

// заголовок календаря
$calendar_head = '
  <tr>
	<th colspan="2"><a href="?ym='.date("Ym", mktime(0,0,0,$month-1,1,$year)).'">« Пред</a></th>
  	<th colspan="3">'.date("F, Y", mktime(0,0,0,$month,1,$year)).'</th>
  	<th colspan="2"><a href="?ym='.date("Ym", mktime(0,0,0,$month+1,1,$year)).'">След »</a></th>
  </tr>
  <tr>
    <th>Понедельник</th>
    <th>Вторник</th>
    <th>Среда</th>
    <th>Четверг</th>
    <th>Пятница</th>
    <th>Суббота</th>
    <th>Воскресенье</th>
  </tr>';

Я думаю здесь уже нечего объяснять комментариев кажется достаточно, единственно я бы хотел пояснить почему 6 строк ведь недель в месяце всего четыре так вот, так как мы месяц начинаем выводить не с понедельника, то есть месяц не всегда начинается с понедельника, у нас появляются неполные недели и посчитав максимальное количество неполных и полных недель вы получите шесть недель вот поэтому и шесть). Но так как 6 недель встречаются не очень часто, то последняя строка в таблице чаще всего будет пустой.
Далее осталось написать HTML код и вывести в нужных местах $calendar_head и $calendar_body, ну и прописать CSS стили. Рассмотрим содержание тега <body>:

<!-- таблица для вывода календаря -->
<table id="calendar" width="710" border="1" cellspacing="0" cellpadding="5">
	<thead>
		<?php echo $calendar_head; ?>
	</thead>
	<tbody>
		<?php echo $calendar_body; ?>
	</tbody>
</table>
<!-- таблица для вывода календаря -->

Как видим календарь состоит полностью из таблицы заголовка и тела. Теперь наш календарь выглядит примерно аот так:

calendar without css

То есть осталось прописать CSS стили, ну примерно вот такие:

body{
	margin:0 auto;
	width:800px;
	padding:10px;
}
#calendar{
	border:0px;
}
#calendar tbody tr{
	height:40px;
}
#calendar td{
	width:80px;
	border:0px;
	border:solid 1px #99FF99;
	font-size:22px;
	text-align:center;
}
#calendar th{
	background-color:#4DDBFF;
	border:solid 1px #00CCFF;
	color:#ffffff;
}
#calendar td.none{
	border:0px;
}
#calendar td.holiday{
	background-color:#FF6633;
	border-color:#FF531A;
	color:#94E4FF;
}
.day{
	background-color:#CCFFCC;
	color:#00B32D;
}
#calendar td.today{
	background-color:#FFFF99;
	border-color:#FF531A;
}

Ну вот и все теперь календарь выглядит примерно так:

cakendar witht-css

Весь исходный код можете посмотреть здесь

Еремин6.18.2010 04:06
Актуально. Хотелось бы на одном из сайтов усовершенствовать календарик. У меня задача немного сложнее сейчас мне нужно вывести 2 последующих месяца и определенные промежутки к примеру с сегодняшнего числа по 10ое число каждого месяца выделять другим цветом. К примеру заказы на сентябрь можно успеть сделать до 10го июля, у вас осталось X дней.
Mak6.21.2010 01:06
В принципе не плохо. Вот бы ещё ячейки с датами сделать с закругленными краями.
Аёха1.27.2011 10:01
Можно использовать календарь, написанный на java script, календарь динамический. Пример календаря:
Макс4.10.2011 10:04
В цикле создания таблицы, после закрытия тега (т.е. перед закрытием внешнего цикла) можно добавить ... $calendar_body .= '';//это уже есть if ($day > $daysInMonth) break;//это можно добавить ... Это позволит не создавать лишнюю 6-ю строку таблицы, если там нет дней.
Макс4.10.2011 10:04
Как коряво отобразился комментарий
Макс4.10.2011 11:04
чтобы календарь стал русским(т.е. первый день понедельник), после определения дня недели добавляем $skip=$skip - 1; if ($skip == -1) $skip=6; //Ну и соответственно дни недели в таблице меняем.
    LEmax9.18.2011 08:09
    тогда в строке "if($j==0)//если воскресенье то отмечаем выходной" нужно заменить 0 на 6. И еще, я долго не мог понять, почему у меня не высвечивался сегодняшний день недели. Потом дошло, что просто нужно поменять местами определения, т.е. сначала нужно определить сегодняшний ли день мы получили, если да - отмечаем, если нет - то проверка на выходной или будний день. if((date(j)==$day)&&(date(m)==$month)&&(date(Y)==$year)){//проверяем на текущий день $calendar_body .= ''.$day.''; } else{ if($j ==6) // если воскресенье то отмечаем выходной $calendar_body .= ''.$day.''; else $calendar_body .= ''.$day.''; // в противном случае просто выводим день в ячейке }
      Алексей10.8.2011 08:10
      Люди, пожалуйста, пришлите полностью исправленный код с переводом календаря в русский формат и с правильной проверкой заранее благодарен
Игорь8.7.2011 09:08
Спасибо за скрипт. Я тут себе позволил немного извратиться в css, получилось очень здорово. Примерно так - http://cs5341.vkontakte.ru/u589298/140315676/x_8afab68a.jpg Извините, что выкладываю картинку вКонтакте, на сайте просто нет возможности прикрепить фото, а на хостинге у меня место закончилось :( З.Ы. Кому интересно - пишите, css вышлю на мыло
    Алексей9.9.2011 01:09
    Игорь. Вышли css на мыло - leha_74rus@mail.ru если не сложно... Заранее спасибо)))
    Алексей10.8.2011 08:10
    Игорь пришлите пожалуйста css на alex.pudovkin@freenet.de
    Екатерина1.18.2012 07:01
    Здравствуйте, Игорь! Очень понравился календарь Пришлите css. ekaterinafb@gmail.com
Serg9.2.2011 05:09
Здорово. Игорь- прикольно получилось)
александра1.17.2012 10:01
Доброго времени суток. очень хорош календарь, а не подскажите как в нем сделать ссылку на дате?
    dzantiev1.17.2012 10:01
    ну добовлять ссылку при выводе вот здесь:
    if($j == 0)     // если воскресенье то омечаем выходной
            $calendar_body .= '<td class="holiday"><a href="/* тут url */">'.$day.'</a></td>';
    else{   // в противном случае просто выводим день в ячейке
            if ((date(j)==$day)&&(date(m)==$month)&&(date(Y)==$year)){//проверяем на текущий день
                    $calendar_body .= '<td class="today"><a href="/* тут url */">'.$day.'</a></td>';
            }
            else{
                    $calendar_body .= '<td class="day"><a href="/* тут url */">'.$day.'</a></td>';
               }
    }
    
    ну и наверное пригодятся переменные $year , $month , $day в них храниться полная дата текущего дня
ОСТАВИТЬ КОММЕНТАРИЙ