Monday, July 21, 2008

Calnder using PHP and Ajax

Online calendars are often used in many web applications. Though popular, the logic behind creating a calendar can be scary especially for those who are new to programming. There are many web calendars in the market but some of them are quite complicated. If we are not able to understand the code, it becomes harder for us to customise the calendar to fit into our existing application. As such, we need to create a calendar that can plug itself into any system seamlessly without problems. Whether we are using Wordpress, Mambo/Joomla or Drupal, we should only need to insert one line into our code for the calendar to work. ie something like this:



If you are already bored at this point or not interested to know how to create a web calendar, feel free to see a live demo of the simple calendar here. The installation procedures is in the source code.

Other than configuring the database access for the calendar, I do not want to change other things. With AJAX, I could even make the page static as I navigate between different months in the calendar. In this tutorial, I would like to share with you a simple calendar I created that fufills the objectives discussed above. The tutorial assumes that you have basic knowledge of PHP and SQL but don't worry, the actual code is minimal and you should be able to customise it easily by reading at the comments. I used PHP 4 so that it is compatible with most servers. You should also be able to re-create the calendar easily in other programming languages using the same logic.

The First Step: Problem Identification

Perhaps the hardest part in creating a calendar is to come up with a good solution to display the days of the month in the correct column, ie Monday, Tuesday..etc.

Apr 2006

Sun Mon Tue Wed Thur Fri Sat


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


Let us take April 2006 for example. There are 30 days and 6 rows in the calendar. If we are given a day in the month, say 15, we have to know that it falls on a saturday and is in the third row (third week). We cannot take for granted that the first day is always the first cell in the table (top left cell). Sometimes, we get 4 or 5 weeks in a month. Only if we know how many days are there in a certain month and which day the first of the month falls in only can we construct the calender as shown above.

Getting Crucial information From The PHP Date function

PHP provides a date() function that gives us alot of useful information about the days and months of the year. To built the calendar for any month, We need 2 important pieces of information from the Date function, ie the "number of days in the month" and a "numeric representation of the first day of the month".

I can get today's date easily from the following code:

// get year, eg 2006$year = date('Y');// get month, eg 04$month = date('n');// get day, eg 3$day = date('j');To get the number of days in this month, I will use the both the date and mktime function like so:

// get number of days in month, eg 28$daysInMonth = date("t",mktime(0,0,0,$month,1,$year));The numeric representation of the day of the week ranges from 0 to 6. 0 is sunday and 6 is saturday. Again, to get the numeric first day of this month, the function mktime comes in handy.

// get first day of the month, eg 4$firstDay = date("w", mktime(0,0,0,$month,1,$year));The Monthly Calendar As A 2-D Array

If we look at the calendar again for April 2006, we will see that it is actually a table(grid) filled with values starting from 1 to x (no of days in the month). The first day of the month is a variable though... It can occur in any day of the week. In the table, imagine each cell as having coordinates (x,y), starting from the top left cell as (0,0) and the bottom right cell as (5,6). In the month of April, the first day of the month is stored in coordinate (0,6). So, the plan now is to store the days of the month in a 2-D Array.

Firstly, we want to know the number of cells needed.

// calculate total spaces needed in array$tempDays = $firstDay + $daysInMonth;Then we want to know the number of rows needed.

// calculate total rows needed$weeksInMonth = ceil($tempDays/7);Populating The 2-D Array

Knowing the number of rows and columns in the 2-D array, we can now fill the arrays with values using 2 for-loops. The first cell will start with a value of 1 and the subsequent cells will have their values increased by 1 till it reaches the end of the array.

for($j=0;$j<$weeksInMonth;$j++) {

for($i=0;$i<7;$i++) {


$week[$j][$i] = $counter;




For the month of April, the temporary array should be something like this:

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 32 33 34 35

36 37 38 39 40 41 42

The Magic Offset

As you can see, the array above is not correct. The first day of April, ie value 1 should be in (0,6) instead of (0,0). Remeber the variable $firstDay? It is the numeric representation of the first day of month which happens to be 6 in April 2006. If we subtract $firstDay from all the values in the array, we will get the array as follows:

-5 -4 -3 -2 -1 0 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 32 33 34 35 36

You should now be able to guess what we are going to do next. Looking at the array above, you see that we already got the values we want but we also have some unwanted values. Any number less than 1 or more than $daysInMonth (number of days in a month) should be ignored.

function fillArray() {

// create a 2-d array

for($j=0;$j<$this->weeksInMonth;$j++) {

for($i=0;$i<7;$i++) {


$this->week[$j][$i] = $counter;

// offset the days

$this->week[$j][$i] -= $this->firstDay;

if (($this->week[$j][$i] < 1) || ($this->week[$j][$i] > $this->daysInMonth)) {

$this->week[$j][$i] = "";






This is the core function in the entire calendar generation algorithm.

Displaying The Calendar

Getting the values right in the 2-D array, we are now ready to display them. Now, we will create a table and start looping again using the foreach function.

$val) { echo ""; for ($i=0;$i<7;$i++) { echo ""; } echo "";}?>
Sun Mon Tue Wed Thur Fri Sat

The final display will be like this:

Apr 2006

Sun Mon Tue Wed Thur Fri Sat


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


We now have a plain calendar.

Adding Special Dates To The Calendar

This calendar only tells you "the days of a week" at the moment and is not very useful. Most online calendar will have reminders as well. Say for example, if my birthday falls on the 4th of April, I want the number 4 in the calendar be displayed differently, possible with a hyperlink in which upon clicking on it, will perform some task like redirecting me to a certain page or displaying more information about myself in a popup windows..etc. To do that, we need to a table in the database with at least 6 columns: id, day, month, year, link, desc.

CREATE TABLE calendar (



month VARCHAR( 2 ) NOT NULL ,

year VARCHAR( 4 ) NOT NULL ,

link VARCHAR( 255 ) NOT NULL ,




We then need to insert some data into the table for testing:

INSERT INTO calendar ( id , day , month , year , link , desc )


'', '24', '*', '2006', '', 'Check your web cccount on the 24th of every month. 2006 only!'

), (

'', '5', '11', '2006', 'some_javascript_funtion', 'Olympics, remember to buy ticket from alice.'


'', '2', '1', '2007', 'some_javascript_funtion', 'early 2007. Any new plans for the year?'

), (

'', '9', '*', '*', '', 'Remember to check updates from every month.'


The * under the month or year column means every month or year.

Next, we do a query and extract the important dates for a certain month and store it in an array.

$sql = "SELECT * FROM calendar WHERE (month='$month' AND year='$year') || (month='*' AND year='$year') || (month='$month' AND year='*') || (month='*' AND year='*')";

$rs = $db->query($sql);

while ($rw = $rs->fetchRow()) {


$links[] = array('day'=>$day', 'month'=>$month, 'year'=>$year, 'link'=>$link, 'desc'=>$desc);



If we create a class to generate the calendar, we need to pass the $links array into the class like so:

$cal = &new Calendar($cArray, $today, $links, $css);



The $cArray is a class containing the array for the plain calendar as shown in step 6. The $today variable is today's date. The $links variable contains the important dates in this month. With the $css variable, we can decorate the calendar table and make it look nicer.

Adding AJAX Capability

To make the calendar more user friendly, we want to be able to navigate easily between the months or years without refreshing the page. Thanks to AJAX, we can now do that easily. If the user clicks on "next month" for example, we need to call the AJAX function to refresh the calendar without refreshing the page. We do that using XMLHttpRequest. This is the main code that does the trick.'get', 'quick_calendar.php?m='+m+&y='+y+'&ran='+ran_no);After I get a response from the AJAX function, i need to update the calender. The calendar is wrapped around with the div tag called 'quickCalender'. I just need to rewrite the contents of the tag on the fly.

document.getElementById("quickCalender").innerHTML = http.responseText; Conclusion and Future Improvements

In this tutorial, we went through the concept of how to create a web calendar using AJAX and PHP. I left the details in the code to prevent the tutorial becoming too long and indigestable. If you look at the code hard enough, you will notice that I packed alot of codes in one file. As a good programming practice, I should have broken them down into smaller parts/files. Because the objective of this project is to create a quick "plug and forget" calendar system, I did that on purpose.

Also, the object oriented approach I used in the code may not be flexible enough if I want to have different layouts for the calendar. The problem can be easily fixed by using inheritance, ie creating a superclass for the QuickCalendar class. We can then have BrownCalendar, SpecialCalendar ...etc.

Hope you enjoy reading this tutorial as much as I wrote it. The full demo can be seen here and source code is here.

Bernard Peh specialises mainly in SEO and PHP programming. He is also the web developer behind Web Design. During his free time, he maintains his melbourne web developer blog.

52 comments on this article. Log in to add your comment | Rate this article:


Submitted by Douglas Clifton on November 14, 2006 - 21:59.

dcal is a PHP calendar I wrote a few years ago. It will display any year or month from 1970 to 2037 and includes holidays, moon phases, the vernal and autumnal equinox, summer and winter solstices, and some other goodies including a slick JavaScript slider interface for jumping directly to a particular month.

login or register to post comments

Hi Bernard, just so you know

Submitted by dmackinn on November 23, 2006 - 16:19.

Hi Bernard, just so you know the source code and the demo links appear to be broken.

login or register to post comments

Great Article

Submitted by cianuro on November 23, 2006 - 20:24.

Great article Bernard. Although there are many perfectly decent calendar apps already out there made by the big guys, it's nice to follow along the creative process. And it seems the URLs are fied now. Regards Dave

login or register to post comments

There's a problem...

Submitted by daiBach on November 30, 2006 - 17:22.

If you are in December and try to navigate back one month then the year gets incremented as well e.g. moving from Dec 06 to Nov 06 actually brings up Nov 07.

login or register to post comments

changes to the script

Submitted by bpeh on December 2, 2006 - 10:02.

thanks all esp daibach for pointing out the error, I've updated the script: php calendar. I emailed the admin with the changes but it wasnt updated. I did a typo with the link in the first paragraph. The link in last paragraph is fine.

there is also an extended version

the source code is

login or register to post comments

Good script. On your

Submitted by bichenoubi on December 4, 2006 - 06:39.

Good script. On your website, on the simple version, there is still errors if you go back and froth a couple of time between dec 2006 and jan 2007. On the extended version, there is no problem. One advice, even thought this is not the point of the article, for accessibility reasons, you should remove the hre f = "java script:; "(errors only for evolt filter) and replace it with the ajax function, eg: hre f="quick_calendar2.php ? m=11&y=2006"(errors only for evolt filter). You will only have to change a bit the php code to find a new way to send only calendar html code for your ajax functions (i.e. your already there random var?).

login or register to post comments

thx for your script.but your

Submitted by jabky on December 4, 2006 - 08:30.

thx for your script.but your source code up there are not like your extended version. and i try to change like gichenoubi said but it still doesn't work for me. i'm the newbie in ajax

login or register to post comments

Some quickCalendar fixes

Submitted by kirk837 on January 5, 2007 - 07:13.

1. To fix the Jan->Dec problem in the "simple" version: In createHeader(), in elseif ($prevMonth==0){, need to add the forgotten statement $prevMonth=12;

2. The "jumpiness" of dates in calendar body when changing month to month is fixed by css changes:

td {height: 22px; border: 0px;

.today and .link {padding: 1px;

Jumpiness of the entire page is improved by setting weeksInMonth (in CreateQCalendarArray) to 6 (this sometimes leaves a blank bottom week, but it keeps the rest of the page from jumping).

3. I found it necessary to initialize the links[] array to '' prior to filling it in the "while mysql_fetch_array" loop, to avoid empty array errors at the foreach loop in createBody. Don't know why this isn't a problem for the posted demo.

4. Each next/previous month or year causes the entire css to again be written to the page, making the page increasingly large (to see this, save the page and examine in an editor). Here's a fix: Place css in quick_calendar.css; in function createHeader, read in the css within the "class=calendar" table with fread:

$this->html = "

$this->html .= fread(fopen($this->cssfile,'r'),filesize($this->cssfile));

$this->html .= " ... "

(where $cssfile='quick_calendar.css', passed to function QCalendar through added parameter cssfile; in QCalendar, $this->cssfile=cssfile).

5. Along with quick_calendar.txt (the "simple" version), it would be nice if Bernard would post quick_calendar2.txt for the "advanced" version. (I have done my own; I'd like to compare notes.) It would also be nice if Bernard would fix the erroneous "we-developer" links on this page.

login or register to post comments

Some quickCalendar fixes - continued

Submitted by kirk837 on January 5, 2007 - 23:23.

6. Every change of month or year creates another
around the calendar. (To actually see this, use FireFox with Firebug and set Outline Blocks.) To avoid this, remove from $this->html = " in createHeader(), and remove at the very end of createFooter(). To place a calendar on a (.php) page, surround the php with a div:

(This is only slightly less "quick" than the php-only statement.)

7. Also, throughout css, "a:link" should be "" (Now I can get rid of those underlines!)

login or register to post comments

Starting with Mondays

Submitted by a1phanumeric on January 12, 2007 - 15:05.

You can easily update this script to start with Mondays (therefore having Sat and Sun together at the end of the table) by changing:


and adding:

// Start with Monday

if($firstDay == 1){

$counter = 1;



before the

for($j=0;$j<$this->weeksInMonth;$j++) {

for($i=0;$i<7;$i++) {




loop Simple! Ed.

login or register to post

Post a Comment

You might also like :

Related Posts with Thumbnails