Smoothly connect structured URLs to a simple request-response cycle.
Floe supports several styles of controller and servlet bindings, including support for REST conventions and slowly growing coverage of standard HTTP idioms. It's fast, clean, and easy to understand.
The Membrane Wrapper
In Floe, the concept of a server is simply that of a run-time procedural dispatcher that responds
to incoming requests. In an object-oriented context, this architecture is naturally represented by
interacting Request and Response objects. Floe enables this interaction by the use of
a 'wrapping space' which we call a Membrane. The Membrane is an outer layer
that encapsulates the entire run-time flow control sequence and triggers the final HTTP and content
response to be pushed to output.
What does a cell membrane look like?
Membrane structures are the fundamental mediators of communication between cellular processes (source unknown).
Actual application routines are invoked using the concept of Receptor binding. Servlet style
classes that implement the Receptor interface are attached to the runtime membrane
and are responsible for interpreting the Request and appending results to the Response
buffer. This code is usually located in the index.php reciever file - Apache should be
configured to pass through all dynamic requests to this PHP reciever using mod_rewrite.
require 'config.php'; require 'floe/server/Membrane.php'; require 'floe/server/IdentityDispatcher.php' $server = new Membrane(); $server->attach(new IdentityDispatcher()); $server->run();
By default, receptors are chained in a FIFO sequence, as determined
by the procedural order of their attachment to the Membrane. This design makes it simple to implement
different styles of resource dispatching and share them between multiple apps.
Default Receptors Provided
IdentityDispatcher |
Binds to a controller method based on the named identity segment of a URL | GET /books binds to BooksController->index |
ResourceDispatcher |
Binds to a named controller based on the HTTP method verb of the request | GET /books binds to BooksController->get |
Implementing Concrete Controllers
Floe expects controllers to be in the /app/controllers folder on the server.
Controllers must have an exact naming match between filename and class definition or else they
won't dispatch correctly.
index.controller.php => IndexControllersub/name.controller.php => NameController
A basic example of a controller to be invoked with identity would look like:
class IndexController extends BaseController { function index() { $this->response->write('<h1>Hello World</h1>'); } }
A controller that wraps a REST style resource would look like:
class BooksController extends BaseController { function get() { $this->response->write('Accessed with HTTP GET'); } function post() { $this->response->write('Accessed with HTTP POST'); } function put() { $this->response->write('Accessed with HTTP PUT'); } function delete() { $this->response->write('Accessed with HTTP DELETE'); } function head() { $this->response->write('Accessed with HTTP HEAD'); } }
Mapping the URI Path
The Request object is a read-only reference during the normal flow of an application.
It provides various helper methods and attributes for accessing useful properties of the HTTP
request message, including the UriPath object bound as $request->uri,
which represents the conceptual segments of the currently requested URL.
The best usage reference for the UriPath is currently the UriPathReaderTest.
Rendering PHP Templates
The Response object acts as a buffer for the HTTP headers and content body returned
to the browser that initiated the request. Examples above demonstrated use of the Response->write
method, which isn't anything more than just echoing plain strings back. More useful, is the ability
to render dynamic templates with assigned variables substituted:
class SeussController extends IdentityController { function options() { $this->response->assign('breakfast', array('green','eggs','ham')); $this->response->render('options'); } }
This controller would bind to the URL path /seuss/options and render the following template at
/app/templates/seuss/options.php:
<div> <h3>What's for Breakfast?</h3> <ul> <?php foreach($breakfast as $item) : ?> <li><?php print $item; ?></li> <?php endforeach; ?> </ul> </div>