A simple PHP calendar function
Recently I needed a calendar to display on a site. I looked around for something I could just cut and paste and drop in but I couldn’t find anything, but picked up something I had started about six months earlier and which had then fallen by the wayside. Now calendars aren’t actually very complicated, but they are a bit of a fiddle. The aim of this calendar function is therefore just to produce a skeleton calendar that I can drop into anything, you can stick anything you want in a calendar cell (day) - it doesn’t matter because all the code for content lives outside the calendar. There are css hooks for all the various cells, columns etc. so you can format it exactly how you want.

I wrote this as a CakePHP helper, but at the end of the day it is just a function and there is nothing Cake specific about it.
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | <?php function calendar($year = '', $month = '', $data = '', $base_url ='') { $str = ''; $month_list = array('january', 'febuary', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'); $day_list = array('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'); $day = 1; $today = 0; if($year == '' || $month == '')// just use current yeear & month { $year = date('Y'); $month = date('M'); } $flag = 0; for($i = 0; $i < 12; $i++) { if(strtolower($month) == $month_list[$i]) { if(intval($year) != 0) { $flag = 1; $month_num = $i + 1; break; } } } if($flag == 0) { $year = date('Y'); $month = date('F'); $month_num = date('m'); } $next_year = $year; $prev_year = $year; $next_month = intval($month_num) + 1; $prev_month = intval($month_num) - 1; if($next_month == 13) { $next_month = 'january'; $next_year = intval($year) + 1; } else { $next_month = $month_list[$next_month -1]; } if($prev_month == 0) { $prev_month = 'december'; $prev_year = intval($year) - 1; } else { $prev_month = $month_list[$prev_month - 1]; } if($year == date('Y') && strtolower($month) == strtolower(date('F'))) { // set the flag that shows todays date but only in the current month - not past or future... $today = date('j'); } $days_in_month = date("t", mktime(0, 0, 0, $month_num, 1, $year)); $first_day_in_month = date('D', mktime(0,0,0, $month_num, 1, $year)); $str .= '<table class="calendar">'; $str .= '<thead>'; $str .= '<tr><th class="cell-prev"><a href="' . $base_url . '/' . $prev_year . '/' . $prev_month . '">prev</a></th><th colspan="5">' . ucfirst($month) . ' ' . $year . '</th><th class="cell-next"><a href="' . $base_url . '/' . $next_year . '/' . $next_month . '">next</a></th></tr>'; $str .= '<tr>'; for($i = 0; $i < 7;$i++) { $str .= '<th class="cell-header">' . $day_list[$i] . '</th>'; } $str .= '</tr>'; $str .= '</thead>'; // get the first day of the month $str .= '<tbody>'; while($day < $days_in_month) { $str .= '<tr>'; for($i = 0; $i < 7; $i ++) { $cell = ' '; if(isset($data[$day])) { $cell = $data[$day]; } $class = ''; if($i > 4) { $class = ' class="cell-weekend" '; } if($day == $today) { $class = ' class="cell-today" '; } if(($first_day_in_month == $day_list[$i] || $day > 1) && ($day < $days_in_month)) { $str .= '<td ' . $class . '><div class="cell-number">' . $day . '</div><div class="cell-data">' . $cell . '</div></td>'; $day++; } else { $str .= '<td ' . $class . '> </td>'; } } $str .= '</tr>'; } $str .= '</tbody>'; $str .= '</table>'; return $str; } ?> |
The function parameters are as follows:
- $year - expects a year in 4 digit e.g. 2007
- $month - expects a month in english e.g. january
- $data - an array containing the data for each day of the month e.g.
$data[2] = ‘This is an entry for the 2nd day of the month’;
$data[24] = ‘A link for the 24th of the month‘;The data is any HTML you want - it is up to you to generate it yourself before you hand it to the calendar.
- $base_url - the url to send the back / foward links on to i.e. the address of page (the calendar expects to be in a mod re-written situation e.g. www.flipflops.org/calendar/2008/june)
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* calendar CSS */ table.calendar {width: auto; border: 1px solid #cccccc; border-collapse: collapse; margin: 0px; padding: 0px; background-color: #ffffff;} table.calendar th {background-color: #eeeeee; text-transform: none; color: #444444; padding: 4px; text-align: center; border: 1px solid #eeeeee;} table.calendar th.cell-prev {text-align: left;} table.calendar th.cell-next {text-align: right;} table.calendar th.cell-header {width: 70px; border-bottom: 1px solid #cccccc;} table.calendar td.cell-today {background-color: #e2e8f6;} /* today in the current month */ table.calendar td.cell-weekend {background-color: #F3F5EB;} table.calendar td {border: 1px solid #cccccc;} table.calendar td div.cell-number {text-align: right; font-size: 8px; color: #444444; display: block;} table.calendar td div {display: block; font-size: 10px; text-align: left;} table.calendar thead th {border: 1px solid #cccccc;} |
I use this as a CakePHP helper - if anyone is interested I’ll put up the supporting code showing how it might be used in a view / controller situation.




September 22nd, 2007 at
That’s super nice.
September 23rd, 2007 at
It’s OK - but it does exactly what I want - of course depending on your situation a lot of the code is superfluous - i.e. in a Cake situation - I can ensure that the month and year passed are valid - it becomes a question of where the best place to validate is.
November 23rd, 2007 at
U got a little error in your calendar generation routine
line 109
while($day 1) && ($day 1) && ($day
November 23rd, 2007 at
Thanks - I’ll have a look at that.
January 25th, 2008 at
Great one! Just needed something like this! Thanks for sharing!
One thing is that february is misspelled in the array! febuary vs february!
And maybe change the variable being passed as number of month instead of month name…. also to overcome ‘misspellments’….
January 25th, 2008 at
Plus:
if(($first_day_in_month == $day_list[$i] || $day > 1) && ($day 1) && ($day
January 25th, 2008 at
Post went wrong?
But the at the last if-statement is needs to be
$day is smaller OR EQUAL to $days_in_month!
January 26th, 2008 at
Is this code open source? Can I reuse it? Under what licence?
January 30th, 2008 at
Hi Andy
I’m glad the calendar function is coming in useful for people. Yes you can re-use it - I’m aware that there are a few bugs etc. but I haven’t had a chance to update it yet (apologies)
I intended it to use the MIT license like Cake itself - when I re factored and cleaned up the code a bit.
So anyway feel free to use it but I would really appreciate a reference to the source in the code and if you have blog or website just a quick link back to fliplflops.org - but up to you. Somebody else contacted me about using the coed as the basis for a Cake Helper, but I don’t know if they have released any code yet - but it might be worth looking in the bakery.
Cheers
John
January 30th, 2008 at
Hi Evert
I know there are a few bugs - and thanks for posting details here and as mentioned above in my previous comment I do intend to refactor and then publish this as a proper helper when I get a moment.
In the meantime though it looks like some of you are finding it useful which is great.
John
February 24th, 2008 at
Awesome! Thanks so much!
February 26th, 2008 at
Hello, that’s very nice. Could you please explain how you call the calendar function in a cakephp view ? Thanks again.
April 9th, 2008 at
[…] six months ago I wrote a post about a Simple PHP calendar function I had written and how it was also really easy to use as a CakePHP […]
April 22nd, 2008 at
$base_url - the url to send the back / foward links on to i.e. the address of page (the calendar expects to be in a mod re-written situation e.g. www.flipflops.org/calendar/2008/june)
What do you mean by that?
Can’t get that mod re-written to work. When I click next -> my browser opens some dirs that doesnt exist. What do I have to change? Thanks
May 1st, 2008 at
Hi Peter
The alternative to using it in a mod-rewrite type situation is just putting the year / month in the querystring e.g.
/calendar.php?year=2008&month=june
To go the querystring route you will need to edit line 89 of the function above that generates the back and forward links to output a link + querystring rather than just mod rewrite psuedo directory stuff.
To use something like /calendar/2008/june you will probably need to add a .htaccess file if you don’t have one the rule would need to be something like:
RewriteEngine On
RewriteBase /
RewriteRule ^calendar/([0-9]+)/(*.)$ calendar.php?year=$1&month=$2 [L]
(haven’t checked the above though - but you get the idea…)
p.s. there might still be a bug in the above code that won’t show the last day of the month (can’t remember if I have updated it yet).
p.s. 2 - worth looking at the new version of this at http://www.flipflops.org/2008/04/08/cakephp-calendar-helper/