Dispatcher Actions in Wolf 0.6.0

Published on 14th October, 2009 by Andrew Waters
Permalink | Category: Blog | Tags: wolf, development


Wolf 0.6.0 brings some major changes for plugin developers. In this post, I want to explain how you can start using some of the dispatcher changes, which are the most promising to me.

Dispatcher Actions in Wolf 0.6.0

Download the example code here

Why is this significant?

With this devlopment, we can use the requested URL to dynamically retrieve content from the database, without having to have it exist as a 'page'. This presents the opportunity to scale any Wolf site a lot more than previously possible.

For example, if you use Twitter, you will have probably noticed the following URI structure for a status message link:

http://twitter.com/andrew_waters/status/4844725407

So breaking that down into it's components:

domain/[username]/status/[messageid]

We have two variables - the username and messageid.

Being able to define a structure which easily and adequately deals with content is very exciting. I'm going to go through an example here (which is available for download) which uses a slightly different structure:

domain/user/andrew_waters
domain/status/4844725407

You'd want to do a lot more in a production environment and the twitter example is possible, but would mean that you'd have to write a lot more code to check other pages in your site by bybassing the controller to check for other pages in the DB and return a form of 404 page if nothing was found. So for the sake of simplicity, here goes.

What do you need to do?

Prerequisites

Must have a call to the pages content in the layout:

<?php echo $this->content(); ?>

If the root page (in this case user or status) doesn't exist, the layout from the home page will be inherited.

Writing the plugin

In your plugin index file we need to add a declaration to the setInfos() function's array:

'type'	=>	'both'

This let's the core know that your functions are available outside the administration section and will grant access to the frontend.

You then need to set up an array that you'll use to dispatch the pages, depending on your desired format. There are two types of strings that the Dispatcher can deal with at present - :any and :num. For a username, we will be using strings so we will want to use :any in our dispatcher declaration. For message ID's, the :num format will do just fine. As in:

'/user/:any'	=>	'/plugin/dispatcher/user/$1',

The dollar variable passes the parsed :any parameter to the function.

Your full index file should look like the following:

Plugin::setInfos(array(
	'id'					=>	'dispatcher',
	'title'					=>	'Dispatcher',
	'require_wolf_version'	=>	'0.6',
	'type'					=>	'both'
));

Plugin::addController('dispatcher', 'Dispatcher');

Dispatcher::addRoute(array(
	'/user/:any'			=>	'/plugin/dispatcher/user/$1',
	'/status/:num'			=>	'/plugin/dispatcher/status/$1'
));

Then we want to write the controller and views. In this example, there is no model but you'll probably want to manipulate the URL variables inside your own code to retrieve that users posts or the post content itself from the message id. It depends on your application.

The example has two very simple views for users and status and these are functions that need to be declared in the Controller.

So, the important parts of this controller are the changes in the __construct function to determine if we're in the front end or backend when the page is loaded. Notice that the display() function is the same as when developing backend plugins...

	public function __construct() {
		// This allows us to check if we're being called in the front or the back.
		if (defined('CMS_BACKEND')) {
			$this->setLayout('backend');
		} else {
			$page = $this->findByUri();
			$layout_id = $this->getLayoutId($page);
			$layout = Layout::findById($layout_id);
			$this->setLayout($layout->name);
		}
	}

	public function user($username) {
		$this->display('../../plugins/dispatcher/views/front/user', array('username' => $username));
	}

Summary

Hopefully this helps to start you on the track to using dispatchers to their full potential. If there's enough interest I may write a follow up post with some more ideas. I've got a ton of ideas for what I want to do with these on a few client projects coming up soon :D

Download the example code here