electronic.alchemy :: Controller
where the past meets the future
pike > Fins > Developer > Controller


Created by hww3. Last updated by hww3, 18 years ago. Version #1.

The "C" in MVC stands for Controller, which is in many ways the most important component of the MVC triad. The controller's purpose is to act as the central switching center for incoming requests, routing data to the model and returning views back to the requestor. We've taken advantage of many of Pike's object oriented features to make working with controllers painless.

The most basic of the controllers available in Fins is Fins.FinsController. It's pretty simple, and is a good starting point. There are other controllers derived from FinsController, such as XMLRPCController and DocController. You can even derive your own for special purposes.

Each application has a "master controller", which is like the root of the virtual filesystem for your web application. This master controller, specified as the controller -> class entry in your application's config file, serves the root directory of the application, that is "/" and everything directly underneath it. You can mount sub-controllers from within this master controller in order to build a more complex directory structure for your application. You can also mix and match different types of controllers to achieve your desired result.

The event handler method

For each path component you want to respond to in your application, you need to provide an event handler function. The index function is a special case, and will be described separately. For example, if we wanted to respond to /foo, we'd need to add an event handler function called foo() to our master controller. An example event handler function for the default FinsController controller type might be:

public void foo(Fins.Request id, Fins.Response response, mixed ... args)

AS you can see, a FinsController event takes 3 arguments: an object representing the request, an object representing the response, and a set of optional arguments. The optional arguments are what you'd consider the PATH_INFO in traditional CGI scripting, and they're provided split on the slash (/) character.

You'll note that event handlers don't return a value. The Fins.Response response object represents the response that will be returned to the client, and you'll control what that ends up being by calling methods in the response object.

The simplest possible controller might look like this:

inherit Fins.FinsController;

public void index(Fins.Request id, Fins.Response response, mixed ... args) { response->set_data("Hello, World."); }

This event handler will simply return the string "Hello, World." to the client. By default, the response will carry a MIME type of text/html. You can use the set_type() method in the response object to change that to whatever you'd like.

The response object provides a number of useful methods that you can use to return a not-found message, set headers and cookies, and return data from Views. Most of these are self explanatory, and you can browse the http://hww3.riverweb.com/dist/Fins/modref/ex/predef_3A_3A/Fins/Response.html for details.

Adding Sub-controllers

It's easy to add sub-controllers to extend your virtual filesystem and break the various tasks of your application down to more manageable and logical chunks. To do this, we create a start() ~~method in our controller and use the ~~load_controller() to add new sub-controllers. Note that we use this technique in order to support the ability to reload controllers when they're updated, a valuable time-saver when developing your applications.

Consider the following sample controller:

inherit Fins.FinsController;

Fins.FinsController oats; Fins.FinsController peas; Fins.FinsController beans;

void start() { oats = load_controller("oats_controller"); peas = load_controller("peas_controller"); beans = load_controller("beans_controller"); }

The arugment passed to load_controller() is a string containing the path name of the controller we want to load, relative to the application's classes directory.

Each controller will be mounted as a subdirectory with the same name as the variable you assign the controller to. For example, if the class above were the master controller, we could access oats_controller as /oats/. Any subpaths will call the appropriate methods or sub-controllers just as they do for the master controller.

Not categorized | RSS Feed | BackLinks

comments powered by Disqus