Long Polling – tutorial, part 0

I was encouraged by good response on my first tutorial, so started to work on another. Unfortunately I didn’t finish it before my vacation, so I almost lost track of what I was doing. So I decided to ship it to you in parts, so by doing every part before publishing I’ll be back on track, and find more mistakes, so hopefully it will be error-free. Enjoy.

What’s long pooling

Long pooling is one of the method that mimics “server push” behavior on stateless HTTP protocol (which is based on “server pull” principle) . Even though there are web sockets coming, I think it’s a good idea to get familiar with that kind of technique.

We’ll try to create just a bit of simple idea. Combination of chat and bulletin board, where You can post Your messages and can see other users messages appearing in “real time”.

We’ll do it with cakePHP on the server side and http://jquery.com/ on the client side. I assume You are a little bit familiar with that tools – I wouldn’t explain how to configure database connection in cakePHP etc.

The only features on this system are

  • creating new discussion
  • replying in a discussion without reloading a page
  • getting users to see other people replies without reloading the page

on top of that we’ll keep in mind that we are on small budget, so we want our application to be as light for the server as possible (to do that we’ll push as much work to client side as we can).

Preparing project

Let’s get last stable version of cake to get started fast:

$ git clone http://github.com/cakephp/cakephp.git longPolling

Then let’s create a database for our discussions

CREATE TABLE `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `lft` int(11) DEFAULT NULL,
  `rght` int(11) DEFAULT NULL,
  `message` text COLLATE utf8_unicode_ci NOT NULL,
  `modified` datetime NOT NULL,
  UNIQUE KEY `id` (`id`),
  KEY `parent_id` (`parent_id`),
  KEY `lft` (`lft`),
  KEY `rght` (`rght`),
  KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

As You can see, we’ll use “Nested set model” which is implemented by Treebehavior. For maximum simplicity discussions don’t have topics and so, and to start discussion one should just post first message outside of any discussion.

Let’s bake model, controller and views for CRUD – this will be a foundation we’ll be working on. Just don’t mind validation and associations, neither admin routing – it’s not crucial to the topic. Add Tree behavior to Post model.

Cleanup

Now, we have some mess in our code already. `add` and `edit` views duplicate themselves, so I’ll remove `add` view and force PostsController::add() to render `edit` view:

//posts_controller.php 
	function add() {
		if (!empty($this->data)) {
			$this->Post->create();
			if ($this->Post->save($this->data)) {
				$this->Session->setFlash(__('The post has been saved', true));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The post could not be saved. Please, try again.', true));
			}
		}
		$this->render("edit");
	}

and, just to make it not look silly – surround code that generates “delete” link with one if statement:

		<?php if(!empty($this->data["Post"]["id"])): ?>
			<li>Html->link(__('Delete', true), array('action' => 'delete', $this->Form->value('Post.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('Post.id'))); ?>
		<?php endif; ?>

To finally polish it – remove user_id, lft, rght, modified fields from the form (because there will be automatically filled).

Oh! I almost forgot, to be able to pick some of the existing topics as parent for message you are adding – create that method in PostsController and call it in add and edit actions:

//posts_controller.php
function _getParentPosts(){
	$this->set('parents', $this->Post->find("list"));
}

Now create at least one discussion, so we can start working on some stuff. If it’s not fun for You just run this query:

INSERT INTO `posts` VALUES (1,NULL,NULL,1,8,'first message in the topic.','0000-00-00 00:00:00'),
(2,1,NULL,2,5,'my very first reply to the very first message!','0000-00-00 00:00:00'),
(3,1,NULL,6,7,'I just have some opinion about first message, and will share it with you... soon.','0000-00-00 00:00:00'),
(4,2,NULL,3,4,'I think you shouldn\'t make off-topics here','0000-00-00 00:00:00');

Now we’re up and running, and ready for the fun stuff.

Share Button