Creating iCalendar (ics) files with PHP
January 2nd 2008 06:56 pm
For a past project, I needed to create iCalendar files from event data stored in a database. There is an iCalendar class on phpclasses.org, but there is very little documentation and you need to understand some of the quirks of the iCalendar specification for it to be useful.
Since I got stumped on trying to get the class working, I went to the specs and figured out how to do it without using the class. Here are some links that I found helpful:
An iCalendar file is just a text file, so creating it is not difficult - it’s figuring out the quirks of the specification and understanding what the different properties mean that is frustrating. Of course the other frustrating thing is that there seem to be differences in how calendar applications parse ics files, and which fields they consider to be required.
Here’s the MySQL Table Schema that I’m using for my calendar table:
CREATE TABLE calendar ( id INT(11) NOT NULL AUTO_INCREMENT, title TINYTEXT, description TEXT, startDate DATE NOT NULL DEFAULT '0000-00-00', endDate DATE NOT NULL DEFAULT '0000-00-00', PRIMARY KEY (id) )
And here’s the PHP that I used. Note that this code currently does not export ics files that can be used by Mozilla Sunbird. It works with MS Outlook 2003, which is my current target client.
// database connection include_once('db.php'); // Dates must be in the format YYYYMMDD $events = $conn->execute("SELECT id, title, DATE_FORMAT(startDate,'%Y%m%d') AS start, DATE_FORMAT(DATE_ADD(endDate, INTERVAL 1 DAY),'%Y%m%d') AS end, startDate, endDate, description FROM calendar"); // Define the file as an iCalendar file header("Content-Type: text/Calendar"); // Give the file a name and force download header("Content-Disposition: inline; filename=calendar.ics"); // Header of ics file echo "BEGIN:VCALENDAR\n"; echo "VERSION:2.0\n"; echo "PRODID:PHP\n"; echo "METHOD:REQUEST\n"; // Loop through database results and create an event for each item while(!$events->EOF) { echo "BEGIN:VEVENT\n"; // The end date of an event is non-inclusive, so if the event is an all day event or one with no specific start and stop // times, the end date would be the next day. This script is used with a calendar that does not deal with times, just dates, // so the time for all events is set to 000000. echo "DTSTART:".$events->fields[start]."T000000\n"; echo "DTEND:".$events->fields['end']."T000000\n"; // Only create Description field if there is a description if(isset($events->fields[description]) & $events->fields[description] != '') { echo "DESCRIPTION:"; // Remove all linebreaks from description stored in database $description = str_replace(chr(13).chr(10)," ", $events->fields[description]); echo $description."\n"; } echo "SUMMARY:{$events->fields[title]}\n"; echo "UID:{$events->fields[id]}\n"; echo "SEQUENCE:0\n"; echo "DTSTAMP:".date('Ymd').'T'.date('His')."\n"; echo "END:VEVENT\n"; $events->MoveNext(); } echo "END:VCALENDAR\n";


Joe responded on 21 Feb 2008 at 1:34 pm #
The link below is broken. It is the third link the list on top.
link text: ‘# Entire iCalendar Specification’ link: ‘http://rfc.net/rfc2445.html’
Bwhendrickx responded on 11 Mar 2008 at 7:19 am #
Very nice code, but a little bit vague. Which code contains the db.php?? only username, password, etc.? what is: $conn->
because when I execute: Parse error: syntax error, unexpected ‘&’ in /xxxxx/xxxx/xxx/generator.php on line 6
bradym responded on 28 Apr 2008 at 8:45 pm #
Bwhendrickx:
db.php is where the connection parameters are stored. In this case I was using adodb (http://adodb.sf.net) so $conn is the connection object. Here’s the contents of db.php
< ?php
include('adodb.inc.php');
$conn = NewADOConnection('mysql');
$conn->connect(’localhost’, ‘username’, ‘password’, ‘database’);
?>
Also, the > should have been > — WordPress decided to convert it to the HTML entity for me and leave off the semi-colon.. how helpful.
bradym responded on 28 Apr 2008 at 8:46 pm #
Joe: Thanks, but the link seems to be working fine now. Maybe their site was down temporarily.
Nathan responded on 22 Jul 2008 at 2:36 am #
Thanks for this, it’s really cleared things up for me. I was planning on doing this for a project further down the line but now I can get it out there at the start. Cheers
Nathan
Christian Asche responded on 28 Aug 2008 at 1:53 am #
Thank you for the tutorial.
I got an error in Outlook 2007: 0×00040023 Der Internetkalender enthält einen fließenden DTStart Wert …
This fix worked for me:
echo “DTSTART:”.$events->fields[start].”T000000Z\n”;
echo “DTEND:”.$events->fields['end'].”T000000Z\n”;
I just added an Z to DTSTART and DTEND, to get rid of the warning.