DesignPatternStep3

From mi-linux
Jump to navigationJump to search

Main Page >> Advanced Web Technologies >> Workbook >> Week 04 >> Step 3 - Handling user request and creating appropriate command

Step 3 - Handling user request and creating appropriate command

When you create a Request object, it simply populates itself with all the values contained in the $_REQUEST PHP super global variable. So anything passed by the user via $_POST, $_GET etc. will be stored in this object.

You can access the values above via the getProperty function.

// Request.php

//############################################################################
// Request class
//############################################################################
class Request
{
  private $properties;

  //############################################################################
  // constructor
  //############################################################################ 
  function __construct()
  {
    $this->init();
  }
  
  //############################################################################
  // Gets all parameters from GET, POST etc...
  //############################################################################   
  function init()
  {
    $this->properties = $_REQUEST;
    return;
  }
  
  //############################################################################
  // Functions to "set" and "get" properties
  //############################################################################   
  function getProperty($key)
  {
    if(isset($this->properties[$key]))
    {
      return $this->properties[$key];
    }
  }
  function setProperty($key, $val)
  {
    $this->properties[$key] = $val;
  }
}

Another very important tool needed by our Front Controller is the Command Resolver.

Put simply, it works like this: If the user types “index.php?cmd=BlogAddForm” in the address bar, then the command resolver will create and return a “Command_BlogAddForm” object.

It does a bit more than that, obviously. It first checks that the class exists, and that it is a valid class (i.e. it extends the Command object). If something goes wrong, it returns a default Command (Command_BlogIndex in our case).

// CommandResolver.php

require_once("Command.php");
require_once("Command_BlogIndex.php");

//############################################################################
// CommandResolver class
//############################################################################
class CommandResolver
{
  private static $base_cmd;
  private static $default_cmd;
  
  //############################################################################
  // Constructor
  //############################################################################    
  function __construct()
  {
    if(!self::$base_cmd)
    {
      // To check if requested command is a valid command
      self::$base_cmd = new ReflectionClass("Command");
      
      // Default command to be returned if an error occurs
      self::$default_cmd = new Command_BlogIndex();
    }
  }
  
  //############################################################################
  // getCommand creates the appropriate command class, 
  // depending on parameter passed in URL
  //############################################################################    
  function getCommand(Request $request)
  {
    // Get "cmd" parameter from request
    $cmd = $request->getProperty('cmd');

    // If no command passed in, use default one    
    if(!$cmd)
      return self::$default_cmd;
      
    $filepath = "Command_{$cmd}.php";
    $classname = "Command_{$cmd}";
    
    // Check if file containing command class exists
    if(file_exists($filepath))
    {
      require_once($filepath);
      
      // Check if command class exists
      if(class_exists($classname))
      {
        $cmd_class = new ReflectionClass($classname);
        
        // Check of class is a valid command
        if($cmd_class->isSubClassOf(self::$base_cmd))
        {
          // Return new instance of command
          return $cmd_class->newInstance();
        }
      }
    }
    
    // Couldn't find command, return default command
    return clone self::$default_cmd;
  }
}

Now that we have our Front Controller and Command Resolver, let’s create our first command!

First, we need an abstract Command class, from which all our commands will derive. It acts as an interface contract, and says "any class that wishes to be a Command must extend me and implement a doExecute() method".

Here is the code:

// Command.php

//############################################################################
// Command class
//############################################################################
abstract class Command
{
  // Make constructor final so sub-classes can't add parameters to it
  final function __construct(){}
  
  //############################################################################
  // Execute command
  //############################################################################   
  function execute(Request $request)
  {
    // General setup for all commands
    // ...
    
    // Then call specific command code
    $this->doExecute($request);
  }
  
  // Specific command code, to be implemented by each sub-class
  abstract function doExecute(Request $request);
}

Now let’s create our first command. Remember, it needs to extend the Command class.

As you can see, we are keeping the actual code simple for now… a simple print statement will do!

// Command_BlogIndex.php

class Command_BlogIndex extends Command
{
  //############################################################################
  // doExecute
  //############################################################################ 
  function doExecute(Request $request)
  {
    print("Blog Index command");
  }
}

Right, we have a Command Resolver, and our first Command. Let’s update our Controller to take all this into account. The handleRequest function now:

  1. Creates a Request objects (remember, it contains all the values passed via $_GET etc.)
  2. Create a Command Resolver
  3. Passes the Request to the Command Resolver, and gets an actual command back.
  4. Finally, it executes the command.
// Controller.php

  //############################################################################
  // Handles request from user
  //############################################################################   
  function handleRequest()
  {
    // Create object that handles request from user
    $request = new Request();
    
    // Create object that decides which command to create depending on request
    $cmd_r = new CommandResolver();
    
    // This function return the appropriate command
    $cmd = $cmd_r->getCommand($request);
    
    // Execute command
    $cmd->execute($request);
  }

Oh, also don't forget to add these at the top of your controller file:

require_once("Request.php");
require_once("CommandResolver.php");

Checkpoint

Your website should now display "Blog Index command".

Again I know, it’s not exactly an overwhelming result, but your application is now doing a lot more! As well as creating a Front Controller and a Registry, it also creates an appropriate Command and runs it!

Now let’s get our command to actually do interesting stuff.

>> Onto Step 4