PHP calendars can be very useful. You can do
things as simple as showing the date, and as complex as an online
booking system. In this tutorial we will show you how to generate a
very simple PHP calendar.
Introduction
March 2010
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Here's a very simple, but very complete, PHP script to print out a calendar. It does one thing, but does it well (which is how it should be). Neat bonus features include the ability to link certain days in the calendar to a web page - useful for a weblog. You can also assign stylesheet classes to specific days, and provide content for an individual day.
To use this code, just save the script to your server, include() it in your code, and display the output of generate_calendar().
New features: Version 2.1 is now locale-aware. All day and month names are automatically generated specific to your locale. Version 2.2 allows you to choose what day your weeks start on. See examples in the examples section.
Functions
Just one:
function generate_calendar($year, $month, $days = array(), $day_name_length = 3, $month_href = NULL, $first_day = 0, $pn = array())
generate_calendar returns a string containing the output HTML. $year and $month are obvious. However, a neat side effect of using PHP's mktime function internally is that generate_calendar does "date rounding". So, basically, if you try to do month 13 of 2002, it'll round to January of 2003. See the documentation for mktime.
$days is an optional array that can contain information you want to specify for each day, including a location to link that day to, a stylesheet class for that day, and any content you want to appear for that day of the calendar. For example, an array passed for the days parameter might look something like this:
<?php
$days = array(
2=>array('/weblog/archive/2004/Jan/02','linked-day'),
3=>array('/weblog/archive/2004/Jan/03','linked-day'),
8=>array('/weblog/archive/2004/Jan/08','linked-day'),
22=>array('/weblog/archive/2004/Jan/22','linked-day'),
);
?>
Each key corresponds to the day of the month, and each value is an array containing one to three elements. The first element is the location you want the day to link to, the second element is a space-separated list of classes (for stylesheets), and the third element is content that you want to appear in that day's cell, instead of just the day's number.
$day_name_length (optional, defaults to 3) is the number of characters to show for the day name ("Monday", "Tuesday", etc.). If you choose zero, the day headings don't display at all, and if you choose >3 it displays the whole name of the day.
$month_href is the location you'd like the month to be a link to (optional).
$first day is the number of the day you want your weeks to start on. Sunday is 0, Monday is 1, etc. Defaults to 0, hence Sunday.
$pn contains the links for the previous and next months to link to (hence, 'pn'). It should be in the following format: $pn = array('<'=>'prev-link','>'=>'next-link'); Note that it's not necessary that the key for next and previous be < (<) and > (>). They could also be things like ← (←) and → (→) or « («) and » (»). In addition, it's important that you define them in the order just shown (previous before next in the array). If you just want to have a previous link, just define the first. If you just want to have a next link, you must define the first with a NULL key and then define the second. If one of the "directions" is defined but the link field is blank, the key (such as < or >) will still be shown, but it won't be a link.
Examples
Show the current month
March 2010
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Code
<?php
$time = time();
echo generate_calendar(date('Y', $time), date('n', $time));
?>
All color and style information is configurable with stylesheets.
Specify the number of characters to show for day name
March 2010
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Code
<?php
$time = time();
echo generate_calendar(date('Y', $time), date('n', $time), NULL, 2);
?>
As you can see, it only shows the first two letters of each day heading.
Highlight the current day
A few people have asked if it is possible to do this. The code is built to be extensible so you can do whatever you want with it.
March 2010
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Code
<?php
$time = time();
$today = date('j',$time);
$days = array($today=>array(NULL,NULL,'<span style="color: red; font-weight: bold; font-size: larger; text-decoration: blink;">'.$today.'</span>'));
echo generate_calendar(date('Y', $time), date('n', $time), $days);
?>
Link or provide content for certain days
January 2004
Sun Mon Tue Wed Thu Fri Sat
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 twenty-six 27 28 29 30 31
Code
<?php
$days = array(
2=>array('/weblog/archive/2004/Jan/02','linked-day'),
3=>array('/weblog/archive/2004/Jan/03','linked-day'),
8=>array('/weblog/archive/2004/Jan/08','linked-day'),
22=>array('/weblog/archive/2004/Jan/22','linked-day'),
26=>array(NULL,'linked-day textual','twenty-six'),
);
echo generate_calendar(2004, 1, $days, 3, '/weblog/archive/2004/Jan');
?>
I added the "twenty-six" so I could show how the content field works. I've used the content field as part of a task manager script I wrote. Using this feature it was easy to give myself a month's view of my tasks. The content for each day was just the text of that day's tasks. In another view, using the stylesheet classes I was able to have each day be highlighted to be a certain color depending on the highest priority task for that day. So I've gotten a lot of use out of this code.
It's important to note, however, that the content field will not be automatically HTML-escaped for you, while the link and CSS classes fields will be. That's to give you the most flexibility while putting content in your calendar, but you must make sure you escape your HTML yourself for that field.
Locale-awareness (new in 2.1): Dutch
As of version 2.1, this code is completely locale-aware. The day and month names are generated from your locale.
March 2010
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Code
<?php
$time = time();
$oldlocale = setlocale(LC_TIME, NULL); #save current locale
setlocale(LC_TIME, 'nl_NL'); #dutch
echo generate_calendar(date('Y', $time), date('n', $time));
setlocale(LC_TIME, $oldlocale);
?>
Spanish, weeks start on Monday (new in 2.2)
March 2010
Mon Tue Wed Thu Fri Sat Sun
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Code
<?php
$time = time();
$oldlocale = setlocale(LC_TIME, NULL); #save current locale
setlocale(LC_TIME, 'es_ES'); #Spanish
echo generate_calendar(date('Y', $time), date('n', $time), NULL, 3, NULL, 1);
setlocale(LC_TIME, $oldlocale);
?>
With previous and next links (new in 2.3)
« August 2004 »
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Code
<?php
$pn = array('«'=>'/weblog/archive/2004/Jul', '»'=>'/weblog/archive/2004/Sep');
echo generate_calendar(2004, 8, NULL, 3, NULL, 0, $pn);
?>
Note that the arrows inherit whatever style you set for your caption (css class 'calendar-month'), but you can set styles for them specifically. They're in <span> tags with classes of "calendar-prev" and "calendar-next".
Notes
Some calendar scripts will print out an entire year for you. I found that kind of unnecessary, since it's real easy to do yourself, and if you do it yourself you can format it any way you want. Here's (basically) the code I use to print the year in my weblog archive:
<table style="margin: auto">
<tr>
<?php for($month=1; $month<=12; $month++){ ?>
<td style="vertical-align: top">
<?php $weblog->printCalendar($year, $month); ?>
</td>
<?php if($month%3 == 0 and $month<12){ ?>
</tr><tr>
<?php } ?>
<?php } ?>
</tr>
</table>
$weblog->printCalendar() does some things like retrieve the list of days that have entries before it calls generate_calendar to print out the calendar.
Note that the function must be given a date on or after 1970 due to limitations in underlying libraries.
|