Controller

I need to implement a Controller, since I’m applying the MVC pattern. I will continue to focus on player management and because I am concentrating on a single module with a limited functionality set, I actually do not need a front controller. However, I know that I will have a whole range of modules in my application (e.g. player management, messaging, trade, military activity, intelligence, etc.) and I will now try to think through whether to use or not to use a front controller.

When coding with PHP, functionality can be grouped into separate PHP scripts. Each of these scripts can act as a controller for functionality contained within the script (i.e. module). This sounds good and very much feasible. However, when I played around with some code, arranging this and that here and there, I noticed that each of my scripts contained "standard initializing stuff" (e.g. timing, require_onces and some logging related stuff). Because of this, I decided to go with a common front controller, the "crithum.php". I also have a feeling that I might need to add more common functionality into this front controller in the future. Such functionality could include session management and possibly zlib.

So, a front controller it is. Let’s make it a simple one:

<?php
// Timing
define("STIME", microtime(true));
// Load constants
require_once(..);
// Load helpers
require_once(..);

// Debug log init
..

// Choose page controller
$pc_name = $_GET['c'] . "PageController";
$c = new $pc_name();
$c->execute();

According to the above code, if we want to direct our request to some certain module, we need to "select" the appropriate (page)controller with the "c" parameter. I did implement a plain PageController as well, just as a fallback if someone tries to access the game without the "c".

But what is a controller then? A controller’s responsibility is to receive requests from the user (the player in my case) and dispatch them to some appropriate piece of code, which knows how to process the request. This piece of code, which might be a class, a function or just inline code within the main controller, is also part of the controller concept. This code uses the model as it sees fit: it requests for data and manipulates the data according to predefined business logic. I also consider preparing the data, which will be displayed by the view, as a controller task. One might think that the view could ask the model for any required (displayable) data and yes, this is true. However, this would result in additional (redundant) data access since usually the controller has already fetched the relevant data for its own purposes and since it’s already here.. you know. We have it, we use it.

To summarise, the main tasks for an MVC based Controller are:

  • Receive and dispatch received requests
  • Manipulate the data model according to business logic
  • Prepare data for the view

In some frameworks, such as Struts, each request is dispatched to an "action" - a piece of code implementing a particular user GUI action. If I remember correctly, these actions were implemented in their own classes and we could follow this way in PHP, too. However, in a simple application (such as mine), controller inline code should be sufficient. Below is a version of my player management controller:

<?php
class PlayerPageController extends PageController {
    
    public function execute() {
        // Dispatch according to user action
        switch ( @$_GET['do'] ) {

            // Show create player screen
            case 'show-create':
                include('lib/view/player/show_create.php');
                break;

            // Create new player
            case 'create':
                // Validate input
                ..
                // Bail out on validation errors 
                if (count($this->appmsgs) > 0) {
                    $p = new Player();
                    $p->name = $name; // Preserve name only
                    include('lib/view/player/show_create.php');
                    break;
                }
                
                // Create player
                ..
                // Forward to browsing players screen
                include('lib/view/player/show_browse.php');
                break;
            // Show modify existing player
            case 'show-modify':
                // Fetch player info for view
                ..
                $p = PlayerDAO::getById($_GET['id']);
                include('lib/view/player/show_modify.php');
                break;

            // Modify player
            case 'modify':
                // Validate input
                ..
                // Bail out on validation errors 
                if (count($this->appmsgs) > 0) {
                    $p = PlayerDAO::getById($id);
                    $p->name = $name; // Preserve name
                    include('lib/view/player/show_modify.php');
                    break;
                }
                
                // Modify
                ..
                // Show modify player screen
                include('lib/view/player/show_modify.php');
                break;

            // Show browse players
            case 'show-browse':
                // Fetch players info for view
                $players = PlayerDAO::getAll();
                include('lib/view/player/show_browse.php');
                break;
            
            // Delete existing player
            case 'delete':
                // Delete player
                ..
                // Fetch players for view
                $players = PlayerDAO::getAll();
                include('lib/view/player/show_browse.php');
                break;
        }
    }
}

Notice! There is no access control (authorization) implemented in the above example! Securing your application is important! I’ll probably write about this in some other blog post some other day.

Since my PlayerPageController was extended from the PageController class, I assume I better give some explanation of that one as well. It contains common properties and functions used in all controllers (big surprise). Among these are arrays to hold application messages and erroneous form fields.

<?php
class PageController {
    
    // Application messages (such as error message) to be displayed to the user
    public $appmsgs = array();
    // Form fields containing errors
    public $errfields = array();
                
    public function add_application_msg($type, $text, array $fields = null) {
        $msg = array("type" => $type, "text" => $text, "field" => $fields);
        // Add message
        $this->appmsgs[] = $msg; 
        // If error, add to error fields
        if ($type == "ERROR" && $fields) {
            foreach($fields as $field) {
                $fieldarray = $this->errfields[$field];
                if ($fieldarray) {
                    $fieldarray[] = &$msg;
                } else {
                    $this->errfields[$field] = array(&$msg);
                }
            }
        }
    }
}

Happy coding!!

Let the discussion continue in the forum!