An Introduction to the Front Controller Pattern, Part 2

Share this article

Front Controllers act like centralized agents in an application whose primary area of concern is to dispatch commands, either statically or dynamically, to predefined handlers such as page controllers, REST resources, or pretty much anything else that comes to mind. Building at least a naive front controller is a pretty instructional experience in understanding the nitty-gritty of them, and to promote this idea from a pragmatic standpoint, I went through the implementation of a contrived front controller in the introductory article
which packaged all the logic required for routing and dispatching requests inside the boundaries of a single class. One of the best things about front controllers is that you can keep them running as tight structures, just routing and dispatching incoming requests, or you can let your wild side show and implement a full-fledged RESTful controller capable of parsing HTTP verbs, accommodating pre/post dispatch hooks, and the like, all behind a unified API. But while this approach is appealing, it breaks the Single Responsibility Principle (SRP) and goes against the nature of OOP itself which actively pushes the delegation of different tasks to several fine-grained objects. So does this mean I’m just another sinful soul who dared to break from the commandments of the SRP? Well, in a sense I am. So I’d like to wash away my sins by showing you how easy is to deploy a small, yet extensible, HTTP framework capable of putting to work a front controller along with the ones of a standalone router and a dispatcher. Plus, the whole request/response cycle will be independently handled by a couple of reusable classes, which naturally you’ll be able to tweak at will. With such a huge proliferation of HTTP frameworks available packaged with full-featured components, it seems absurd to implement from scratch a front controller that routes and dispatches requests through a few modular classes, even if these ones retain the essence of the SRP. In a humble attempt to avoid being judged for reinventing the wheel, some chunks of my custom implementation will be inspired by the nifty EPHPMVC library written by Lars Strojny.

Dissecting the Request/Route/Dispatch/Response Cycle

The first task we should tackle is defining a couple of classes charged with modeling the data and behavior of a typical HTTP request/response cycle. Here’s the first one, coupled to the interface that it implements:
class Request {

  public function __construct($uri, $params) { 
    $this->uri = $uri;
    $this->params = $params;
  }
 
  public function getUri() {
    return $this->uri;
  }
 
  public function setParam($key, $value) {
    $this->params[$key] = $value;
    return $this;
  }
 
  public function getParam($key) {
    if (!isset($this->params[$key])) {
      throw new \InvalidArgumentException("The request parameter with key '$key' is invalid."); 
    }
    return $this->params[$key];
  }
 
  public function getParams() {
    return $this->params;
  }
}
The Request class encapsulates an incoming URI along with an array of parameters and models an extremely skeletal HTTP request. For the sake of brevity, additional data members such as the set of methods associated to the request in question have been deliberately left outside of the picture. If you feel in the mood to drop them into the class, go ahead and do so. Having a slim HTTP request wrapper living happily on its own is all well and fine sure, but ultimately useless if not coupled to the counterpart that mimics the data and behavior of a typical HTTP response. Let’s fix and build up this complementary component:
class Response {
  public function __construct($version) {
    $this->version = $version;
  }
 
  public function getVersion() {
    return $this->version;
  }
 
  public function addHeader($header) {
    $this->headers[] = $header;
    return $this;
  }
 
  public function addHeaders(array $headers) {
    foreach ($headers as $header) {
      $this->addHeader($header);
    }
    return $this;
  }
 
  public function getHeaders() {
    return $this->headers;
  }
 
  public function send() {
    if (!headers_sent()) {
      foreach($this->headers as $header) {
        header("$this->version $header", true);
      }
    } 
  }
}
The Response class is unquestionably a more active creature than its partner Request. It acts like a basic container which allows you to stack up HTTP headers at will and is capable of sending them out to the client too. With these classes doing their thing in isolation, it’s time to tackle the next part in the construction of a front controller. In a typical implementation, the routing/dispatching processes are most of the time encapsulated inside the same method, which frankly speaking isn’t that bad at all. In this case, however, it’d be nice to break down the processes in question and delegate them to different classes. This way, things are balanced a little more in the equally of their responsibilities. Here’s the batch of classes that get the routing module up and running:
class Route {

  public function __construct($path, $controllerClass) {
    $this->path = $path;
    $this->controllerClass = $controllerClass;
  }
 
  public function match(RequestInterface $request) {
    return $this->path === $request->getUri();
  }
 
  public function createController() {
   return new $this->controllerClass;
  }
}

 
class Router {
  public function __construct($routes) {
    $this->addRoutes($routes);
  }
 
  public function addRoute(RouteInterface $route) {
    $this->routes[] = $route;
    return $this;
  }
 
  public function addRoutes(array $routes) {
    foreach ($routes as $route) {
      $this->addRoute($route);
    }
    return $this;
  }
 
  public function getRoutes() {
    return $this->routes;
  }
 
  public function route(RequestInterface $request, ResponseInterface $response) {
    foreach ($this->routes as $route) {
      if ($route->match($request)) {
        return $route;
      }
    }
    $response->addHeader("404 Page Not Found")->send();
    throw new \OutOfRangeException("No route matched the given URI.");
  }
}
As one might expect, there’s a plethora of options to choose from when it comes to implementing a functional routing mechanism. The above, at least in my view, exposes both a pragmatic and straightforward solution. It defines an independent Route class that ties a path to a given action controller, and a simple router whose responsibility is limited to checking if a stored route matches the URI associated to a specific request object. To get things finally sorted out, we would need to set up a swift dispatcher that can be put to work side by side with the previous classes. The below class does exactly that:
class Dispatcher {

  public function dispatch($route, $request, $response)
    $controller = $route->createController();
    $controller->execute($request, $response);
  }
}
Scanning the Dispatcher, you’ll notice two things about. First, it doesn’t carry any state. Second, it implicitly assumes that each action controller will run under the surface of an execute() method. This can be refactored in favor of a slightly more flexible schema if you wish (the first thing that comes to my mind is tweaking the implementation of the Route class), but for the sake of simplicity I’ll keep the dispatcher untouched. By now you’re probably wondering how and where to drop a front controller capable of bring all of the previous classes together. Don’t be anxious, as that’s next!

Implementing a Customizable Front Controller

We’ve reached the moment we’ve all been waiting for since the very beginning, implementing the long awaited front controller. But if you were expecting the implementation to be pretty much some kind of epic quest, given the number of classes that we dropped up front, I’m afraid you’ll be disappointed. In fact, creating the controller boils down to just defining a class that shields the functionality of the router and the dispatcher behind a ridiculously simple API:
class FrontController {

  public function __construct($router, $dispatcher) {
    $this->router = $router;
    $this->dispatcher = $dispatcher;
  }
 
  public function run(RequestInterface $request, ResponseInterface $response) {
    $route = $this->router->route($request, $response);
    $this->dispatcher->dispatch($route, $request, $response);
  }
}
All that the FrontController class does is employ its run() method for routing and dispatching a given request to the corresponding action controller by using the behind-the-scenes functionality of its collaborators. If you’d like, the method could be a lot fatter and encapsulate a bunch of additional implementation, such as pre/post dispatch hooks and so forth. I’ll leave this as homework for you in case you want to add a new notch to your developer belt. To see if the front controller set up is actually as functional as it seems, let’s create a couple of banal action controllers which implement an execute() method: In this case, the sample action controllers are pretty simple creatures that don’t do anything particularly useful other than outputting a couple of trivial messages to screen. The point here is to demonstrate how to call them via the earlier front controller, and pass along the request and response objects for some eventual further processing. The following snippet shows how to accomplish this in a nutshell:
$request = new Request("http://example.com/test/");
 
$response = new Response;
 
$route1 = new Route("http://example.com/test/", "Acme\\Library\\Controller\\TestController");
 
$route2 = new Route("http://example.com/error/", "Acme\\Library\\Controller\\ErrorController");
 
$router = new Router(array($route1, $route2));
 
$dispatcher = new Dispatcher;
 
$frontController = new FrontController($router, $dispatcher);
 
$frontController->run($request, $response);
Even though the script looks somewhat crowded because it first goes through factoring a couple of routes which are passed into the front controller’s internals, it demonstrates how to get things rolling and call action controllers in a pretty straightforward fashion. Moreover, in the example an instance of TestController will be invoked at runtime, as it effectively matches the first route. Needless to say that the routing can be customized from top to bottom, as calling other action controller is just a matter of passing around a different URI to the Request object, and of course a matched route. Despite of all the up front setup required through the implementation process, the actual beauty of this approach rests on the modularity exposed by each class involved in the request/route/dispatch/response cycle. There’s no need to deal with the oddities of a monolithic front controller anymore, not to mention the fact that most of the objects included in the whole transaction, such as the Request/Response duet, can be easily reused in different contexts or swapped out by more robust implementations.

Closing Thoughts

Though the academic definition of a front controller seems to be pretty rigid as it describes the pattern as a centralized, command-based mechanism narrowed to just dispatching requests, the truth is that in the real world the number of approaches that can be used for getting a functional implementation is anything but scarce. In this quick roundup, my goal was just to demonstrate how to create at least a couple of customizable front controllers from a pragmatic standpoint by appealing first to a compact, tight implementation, where the routing and dispatching processes were packaged inside the limits of one single, catch-all class, and second, through a more granular solution, where the execution of the processes in question were dissected and delegated to a few fine-grained classes. There’s still a lot of additional options out there worth looking, other than the ones showcased here, with each one having their own benefits and drawbacks. As usual, which one you should to pick up depends exclusively on the taste of your picky palate.

Frequently Asked Questions about Front Controller Pattern

What is the main purpose of the Front Controller Pattern in web development?

The Front Controller Pattern is a software design pattern often used in web applications to provide a centralized point of control for handling request handling. This pattern is particularly useful in handling common tasks such as security, routing, and view management in a centralized manner, thereby reducing code duplication and improving maintainability. It’s a part of the Java EE design patterns and is used extensively in modern web frameworks.

How does the Front Controller Pattern differ from the Page Controller Pattern?

The Front Controller Pattern and Page Controller Pattern are both used in web development, but they serve different purposes. The Front Controller Pattern provides a centralized entry point for handling requests, while the Page Controller Pattern deals with the action to be taken based on the request. In other words, the Front Controller Pattern is responsible for routing requests to the appropriate handlers, while the Page Controller Pattern is responsible for processing the request and generating the response.

Can you provide a simple example of the Front Controller Pattern in action?

Sure, let’s consider a simple web application. When a user makes a request, instead of being handled by multiple controllers, the request is first received by a single Front Controller. This Front Controller then processes the request, performs any necessary security checks, and determines the appropriate handler for the request. The handler then processes the request and generates the response. This centralized handling of requests makes the application easier to manage and maintain.

What are the benefits of using the Front Controller Pattern?

The Front Controller Pattern offers several benefits. Firstly, it provides a centralized point of control, making the application easier to manage and maintain. Secondly, it reduces code duplication by handling common tasks such as security and routing in a centralized manner. Thirdly, it improves modularity and separation of concerns by decoupling the handling of requests from their processing.

Are there any drawbacks to using the Front Controller Pattern?

While the Front Controller Pattern offers several benefits, it also has a few potential drawbacks. One potential drawback is that it can lead to a single point of failure if the Front Controller becomes unavailable. Additionally, it can potentially lead to increased complexity if not implemented correctly, as all requests must pass through the Front Controller.

Is the Front Controller Pattern suitable for all web applications?

The Front Controller Pattern is a powerful tool, but it may not be suitable for all web applications. For small, simple applications, using a Front Controller might be overkill and could potentially add unnecessary complexity. However, for larger, more complex applications, the benefits of centralized control and reduced code duplication can make the Front Controller Pattern a valuable tool.

How does the Front Controller Pattern relate to the MVC (Model-View-Controller) pattern?

The Front Controller Pattern and the MVC pattern are often used together in web development. In this context, the Front Controller acts as the initial point of contact for handling all requests, and then delegates the processing of these requests to the appropriate controllers in the MVC framework.

Can the Front Controller Pattern be used with other design patterns?

Yes, the Front Controller Pattern can be used in conjunction with other design patterns. For example, it can be used with the Dispatcher View Pattern to further decouple the handling of requests from their processing. It can also be used with the Intercepting Filter Pattern to pre-process or post-process requests.

How does the Front Controller Pattern handle security?

The Front Controller Pattern can handle security in a centralized manner. This means that instead of implementing security checks in each individual controller, these checks can be implemented once in the Front Controller. This not only reduces code duplication but also makes the application more secure by ensuring that all requests are subject to the same security checks.

How does the Front Controller Pattern improve code maintainability?

The Front Controller Pattern improves code maintainability by centralizing the control of requests. This means that changes to the handling of requests, such as changes to security checks or routing, only need to be made in one place. This makes the code easier to understand, easier to modify, and less prone to errors.

Alejandro GervasioAlejandro Gervasio
View Author

Alejandro Gervasio is a senior System Analyst from Argentina who has been involved in software development since the mid-80's. He has more than 12 years of experience in PHP development, 10 years in Java Programming, Object-Oriented Design, and most of the client-side technologies available out there.

Expert
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form