Create an AJAX Calendar Using PHP
A few years back, I fell into a case where I needed to create a calendar for a project that I was working on. Pulling from my PHP toolbox, I worked with the handy date() and mktime() functions to create a nicely formatted calendar that, when called, displays the current month dynamically. The beauty of using PHP to create this calendar on the fly is that I could later expand its functionality by adding items such as scheduled events and upcoming appointments. I realize that there are a lot of great calendar applications out there, many incorporating awesome AJAX functionality (I live and die by Google's Calendar); however, when working on a large site project, you may decide that you need to create your own customized calendar, full of functionality that doesn't exist in already create packages.
This was the situation I found myself in. I wanted to create a calendar with a full blown back-end that allowed site administrators to add new events on the fly and have them displayed on their site's front page. By having a nice and customized calendar that I created in PHP, I was able to fully integrate an event system into my content management system with ease. In this article, I want to explore how to take a simple calendar system, add a little AJAX/DHTML injection and later expand to integrating with an appointment / event system of some sort.
View an Example of the AJAX Calendar Using PHP
Rendering a Calendar in PHP
Creating a calendar dynamically can be a little tricky to get your head wrapped around at first because of all the variances month to month and year to year. Thankfully, PHP comes to the rescue with some handy functions that will help us, on the fly, get the information we need. The time() function is an extremely helpful starting point. By calling this function, we in return get a UNIX timestamp of seconds since the UNIX Epoch (January 1 1970 00:00:00 GMT). Using the date() function we can determine everything we need from this value– the current day, including day of the week, month and year. This will be our starting place. Figure out the current month and year and store them as a variable.
$month = date('m', time());
$year = date('Y', time());
To make things easier down the road, we want to centralize our code by writing a function that will provide us with a calendar based on two parameters– month and year. By passing these arguments to our function, we will, in return, get a string that will be a properly formatted calendar in HTML. We will be able to place this string anywhere in our web page to display the calendar.
Define the empty calendar function with two parameters, $month and $year, which will be represented as integers. We will call it getCalendar():
function getCalendar($month,$year)
{
}
There are a number of things that we need to figure out for the display of our calendar, all based on the month and year that are to be passed into the function.
- The timestamp for the first day of the month.
- The name of the month.
- The day of the week on which the month starts.
- Number of days in the month.
To acquire the timestamp for the first day of the month, simply use the mktime() function, passing the proper month and year information as arguments. Store this as a variable:
$month_start = mktime(0,0,0,$month, 1, $year);
Now that we have the timestamp, we can use the date function to find both the name of the month and the day of the week the month starts on.
// Get the name of the month
$month_name = date('F', $month_start);
// Figure out which day of the week the month starts on.
$first_day = date('D', $month_start);
With the first day in hand, we can figure out how many table cells we need to offset the first day of the month. We will use a switch statement to do so:
switch($first_day)
{
case "Sun":
$offset = 0;
break;
case "Mon":
$offset = 1;
break;
case "Tue":
$offset = 2;
break;
case "Wed":
$offset = 3;
break;
case "Thu":
$offset = 4;
break;
case "Fri":
$offset = 5;
break;
case "Sat":
$offset = 6;
break;
}
And finally, we need to know how many days we need to display for this month. PHP provides a function to us — cal_days_in_month() which will return the number of days in the month for the specified year and calendar. We will use the Gregorian calendar — represented as the constant CAL_GREGORIAN. Learn more about the Gregorian calendar here.
$num_days_current = cal_days_in_month(CAL_GREGORIAN, $month, $year);
Now that we have all the proper information to output our calendar, it's time to do so. Run a loop and build an array, counting through the days of the current month.
// Count through the days of the current month -- building an array
for($i = 0; $i < $num_days_current; $i++){
$num_days_array[] = $i+1;
}
We also need to figure out how many empty cells we need to display after our month to close out the table. This is done through a series of boolean statements:
if($current_num > 35){
$num_weeks = 6;
$outset = (42 - $current_num);
}
else if($current_num < 35){
$num_weeks = 5;
$outset = (35 - $current_num);
}
if($current_num == 35){
$num_weeks = 5;
$outset = 0;
}
Add the number of outset cells to an array. We'll call this array $new_count
for($i = 1; $i <= $outset; $i++){
$new_count[] = '';
}
Now, since there are seven days in a week, let's chunk our $new_count array into pieces of 7 days.
$weeks = array_chunk($new_count, 7);
Each week is now represented by $week.
We are finally ready to build the header portion of the calendar display.
ob_start();
echo <<<EOS
<table id="calendar">
<tr>
<td><a href="#" class="monthnav" onclick="getPrevMonth();return false;">« Prev</a></td>
<td colspan=5 class="month">$month_name $year</b></td>
<td><a href="#" class="monthnav" onclick="getNextMonth();return false;">Next »</a></td>
</tr>
<tr class="daynames">
<td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td>
</tr>
EOS;
Our next piece of logic is to loop through each week and through each day to output them into our table and if we're on the current date, to add the appropriate class to mark that.
foreach($weeks AS $week){
echo '<tr class="week">';
foreach($week as $day){
if($day == date('d', $current_time) && $month == date('m', $current_time) && $year == date('Y', $current_time))
echo '<td class="today">'.$day.'</td>';
else
echo '<td class="days">'.$day.'</td>';
}
echo '</tr>';
}
echo '</table>';
Our function returns the output:
return ob_get_clean();
To render our calendar, we simply call the function we just built:
$calendar = getCalendar($month,$year);
Adding AJAX Functionality to the PHP Calendar
In our JavaScript, we will set both the current month and year as variables, accessible by the functions we will create, getPrevMonth() and getNextMonth(). We will set these variables to the PHP variables $month and $year, defined above.
var current_month = <?PHP echo @$month ?>;
var current_year = <?PHP echo @$year ?>;
As for getPrevMonth(), this will be called when the user clicks the "« Prev" link we output in our calendar's HTML. Here's how we define this function,
function getPrevMonth()
{
if(current_month == 1)
{
current_month = 12;
current_year = current_year - 1;
}
else
{
current_month = current_month - 1;
}
params = 'month='+current_month+'&year='+current_year;
new Ajax.Updater('calendar_wrapper',window.location.pathname,{method:'post',parameters: params});
}
The function sets the query string, params, that is to be passed in our AJAX request. If you look at the AJAX definition, we are using the Updater() function from Prototype JS. This function will automatically update our defined id, 'calendar_wrapper', with the output from our destination script. In this case, we are pointing the AJAX call to window.location.pathname, the script we are currently working in. We will provide some functionality at the top of this file to identify and handle the AJAX request.
Here's getNextMonth():
function getNextMonth()
{
if(current_month == 12)
{
current_month = 1;
current_year = current_year + 1;
}
else
{
current_month = current_month + 1;
}
params = 'month='+current_month+'&year='+current_year;
new Ajax.Updater('calendar_wrapper',window.location.pathname,{method:'post',parameters: params});
}
Very similar to getPrevMonth(). In fact, these two could easily be consolidated into one function that receives an argument of which direction the user wishes to move; however, for the purpose of this tutorial I decided to keep this functionality separate.
Now, how to handle the AJAX request in our PHP.
Identify an AJAX Request and Rendering the Calendar Month from AJAX
Here's a handy little function I often find myself using to identify whether or not a request is using AJAX headers:
function isAjax() {
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
$_SERVER ['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
}
Now that we have this helper, let's check and see if our request is AJAX and if so, render the correct calendar based on the $_POST values. Place this at the very top of your file:
if(isAjax() && isset($_POST['month']))
{
$month = $_POST['month'];
$year = !isset($_POST['year']) ? date('Y', $current_time) : $_POST['year'];
die(getCalendar($month,$year));
}
We use the die function here as the only code we wish to run is that contained within our if statement.
And there you have it, the pieces that you need to create a calendar in PHP that updates with AJAX requests. This is a great base calendar that you can easily expand upon to provide added functionality as you might need it. Try hooking into your database to provide a calendar of events or upcoming appointments! If you would like to see what my complete script looks like, please view the AJAX Calendar PHP source code.


