CakePHP and Events with AJAX and MySQL (Part 1)

I recently had a customer that needed an event display system. (They’re not paying me, and non-profit, so I feel ok putting this tutorial here). They wanted to have a nice pretty calendar that displayed when certain events happened. I had also decided early on to use CakePHP and had a fairly fleshed out site at this point, so I just wanted to add in another MVC that I could use. This is actually quite easy, thought it takes some setting up, so here is how I did it.

NOTE: This tutorial assumes you have an Acl controlled application, and know how and when to get these things to work. I will explain when things need to be done with ARO/ACO, but not how. Also, I borrowed the design heavily from this calendar tutorial

Step 0: Setting up the DB

This database structure provides a very simplistic event. The event has a title, body (description), date, and ID, and if it reoccurs. You may need less or more things, this will be left to your discretion, this is just to get you started.

CREATE TABLE IF NOT EXISTS `events` (
  `id` int(11) NOT NULL auto_increment,
  `title` varchar(55) NOT NULL,
  `body` text,
  `date` date NOT NULL,
  `recurring` text,
  PRIMARY KEY  (`id`),
  KEY `title` (`title`)
)



Step 1: The Model

I didn’t need anything at all in my model, so I just stole the first few lines from another one and put it there. I’ll put mine here simply for completeness.

class Event extends AppModel {

	var $name = 'Event';

}



Step 2: Setting up the controller

This won’t get in to ACL/ACO/ARO at all, but a hand-waving explanation of how-to-make-it-work. Let’s stub out the controller with what we will eventually need: some setup and 4 methods.

class EventsController extends AppController {

	var $name = 'Events';
	var $helpers = array('Html', 'Form', 'Ajax', 'Javascript');

	function beforeFilter() {
	    parent::beforeFilter();
	    $this->Auth->allowedActions = array('index', 'display');
	}

       	function index(){
        }

	function add($date = ""){
        }

	function delete($id){
        }

	function edit($id = null) {
        }

This will be what we are mainly going to work on. The way mine functions is that there is no way to view an individual event’s details by clicking on it. You could add this in by including a view() method and displaying the info. That will be left as an exercise to the reader.

Step 3: Setting up the index() method

What we need to do here is to get all the events within a certain range (the current month) and to display them out AJAX style. CakePHP makes this trivially easy.

	Configure::write('debug', 0);
	$month = $_POST['m'];
	if ($month < 10) $month = "0".$month;
	$year = $_POST['y'];

	$max = cal_days_in_month(CAL_GREGORIAN, $month, $year);
	$min = "01";

	$this->set('events', $this->Event->find('all', array(
							'conditions' => array("Event.date BETWEEN '$year-$month-$min' AND '$year-$month-$max'"))));
	$this->set('month', $month);
	$this->set('year', $year);

	$this->layout = "ajax";

Explanation:

Configure::write('debug', 0)

- because we’re using AJAX, we don’t want any pesky error messages (or if still in debugging, db calls) to show up.

if ($month < 10) $month = "0".$month;

- later we’ll see javascript gives us the month without a leading 0. this is to put it back.

cal_days_in_month(CAL_GREGORIAN, $month, $year);

- a handy function to give us… exactly what it says. alternative to date(“t”, mktime(….));

Part 2 to happen shortly

  • Ajax-ing in the content
  • Javascript Date() vs PHP date()
  • Correctly padding days before first of the month