Difference between revisions of "6CC001 Workshop - week 04"

From mi-linux
Jump to navigationJump to search
m (Protected "6CC001 Workshop - week 04" [edit=sysop:move=sysop])
 
(56 intermediate revisions by 4 users not shown)
Line 1: Line 1:
[[Main Page]] >> [[CP3207|Web Application Development]] >> [[Web Application Developpment - Workbook|Workbook]] >> Week 04
+
[[Main Page]] >> [[6CC001|Advanced Web Technologies]] >> [[6CC001 - Workbook|Workbook]] >> Week 04
  
== Step 1 - Create and populate database ==
+
Your job today is to implement a blog similar to this one:
 +
* [http://mi-linux.wlv.ac.uk/~in9352/OO/blog/index.php http://mi-linux.wlv.ac.uk/~in9352/OO/blog/index.php]
  
First, let’s create a very simple table to store our blog messages. The following SQL code will create the table and insert a couple of dummy records in it. Simply paste it and run it in phpmyadmin.
+
The different steps are:
  
<pre>
+
# [[DesignPatternStep1|Step 1]] - Create and populate database
CREATE TABLE IF NOT EXISTS `messages` (
+
# [[DesignPatternStep2|Step 2]] - Create the index.php file, front controller and registry class
  `id` int(11) NOT NULL auto_increment,
+
# [[DesignPatternStep3|Step 3]] - Handling user request and creating appropriate command
  `title` varchar(255) NOT NULL,
+
# [[DesignPatternStep4|Step 4]] - Accessing the database
  `message` text NOT NULL,
+
# [[DesignPatternStep5|Step 5]] - Creating our first view
  `date_added` datetime NOT NULL,
+
# [[DesignPatternStep6|Step 6]] - Adding messages
  PRIMARY KEY  (`id`)
+
# [[DesignPatternStep7|Step 7]] - Deleting messages
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=19 ;
 
  
INSERT INTO `messages` (`id`, `title`, `message`, `date_added`) VALUES
+
Let's take it one step at a time... and remember: read and understand the code before pasting it into your text editor!
(1, 'Test 1', 'Hello world!', '2009-07-27 15:06:29'),
 
(2, 'Test 2', 'Hiya', '2009-07-27 15:06:38');
 
</pre>
 
 
 
== Step 2 - Create the index.php file, front controller and registry class ==
 
 
 
Our index file is very simple:
 
 
 
<pre>
 
// The index simply calls the front controller
 
require("Controller.php");
 
Controller::run();
 
</pre>
 
 
 
Next, let's create our Front Controller
 
 
 
<pre>
 
require_once("Registry.php");
 
 
 
//############################################################################
 
// Front Controller class
 
//############################################################################
 
class Controller
 
{
 
  private function __construct(){}
 
 
 
  //############################################################################
 
  // Main "run" function
 
  //############################################################################   
 
  static function run()
 
  {
 
    $instance = new Controller;
 
    $instance->init();
 
    $instance->handleRequest();
 
  }
 
 
 
  //############################################################################
 
  // Init config stuff, e.g. database location, etc.
 
  //############################################################################ 
 
  function init()
 
  {
 
    Registry::set("database_dsn", "mysql:host=localhost;dbname=YOURDBNAME");
 
    Registry::set("database_login", "YOURUSER");
 
    Registry::set("database_password", "YOURPASSWORD");
 
  }
 
 
 
  //############################################################################
 
  // Handles request from user
 
  //############################################################################ 
 
  function handleRequest()
 
  {
 
    print("Hello world!");
 
  }
 
}
 
</pre>
 
 
 
We also need the Registry class:
 
 
 
<pre>
 
//############################################################################
 
// Registry class, used to store values to be used across whole application
 
//############################################################################
 
class Registry
 
{
 
  private static $values = array();
 
 
 
  //############################################################################
 
  // Store a value
 
  //############################################################################   
 
  static function set($key, $val)
 
  {
 
    self::$values[$key] = $val;
 
  }
 
 
 
  //############################################################################
 
  // Get a value
 
  //############################################################################   
 
  static function get($key)
 
  {
 
    if(isset(self::$values[$key]))
 
    {
 
      return self::$values[$key];
 
    }
 
    return null;
 
  }
 
 
 
}
 
</pre>
 
 
 
===Checkpoint===
 
 
 
Your page should display "Hello world!"
 
 
 
== Step 3 - Handling user request and created appropriate command ==
 
 
 
We need a Request class:
 
 
 
<pre>
 
//############################################################################
 
// 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;
 
  }
 
}
 
</pre>
 
 
 
Next, the CommandResolver class:
 
 
 
<pre>
 
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;
 
  }
 
}
 
</pre>
 
 
 
Our parent Command class:
 
 
 
<pre>
 
//############################################################################
 
// 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);
 
}
 
</pre>
 
 
 
And our first command: the Command_BlogIndex class
 
 
 
<pre>
 
//############################################################################
 
// SearchVenueCommand class
 
//############################################################################
 
class Command_BlogIndex extends Command
 
{
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    print("Blog Index command");
 
  }
 
}
 
</pre>
 
 
 
Let's update our Controller class.
 
We now read the request from the user, and use the CommandResolver object to create a Command.
 
 
 
Add these at the top of the file:
 
<pre>
 
require_once("Request.php");
 
require_once("CommandResolver.php");
 
</pre>
 
 
 
And implement the handleRequest function:
 
<pre>
 
  //############################################################################
 
  // 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);
 
  }
 
</pre>
 
 
 
=== Checkpoint ===
 
 
 
Your website should now display "Blog Index command".
 
 
 
== Step 4 - Accessing the database ==
 
 
 
First let's create our Manager class:
 
 
 
<pre>
 
require_once("Registry.php");
 
 
 
//############################################################################
 
// Manager class
 
//############################################################################
 
abstract class Manager
 
{
 
  static $DB;
 
  static $stmts = array();
 
 
 
  //############################################################################
 
  // Constructor
 
  //############################################################################ 
 
  function __construct()
 
  {
 
    // Get DB details from registry
 
    $database_dsn = Registry::get("database_dsn");
 
    $database_login = Registry::get("database_login");
 
    $database_password = Registry::get("database_password");
 
   
 
    // Create connection
 
    $pdo = new PDO($database_dsn, $database_login, $database_password);
 
    self::$DB = $pdo;
 
 
 
    // Set connection attributes   
 
    self::$DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
  }
 
 
 
  //############################################################################
 
  // prepareStatement: prepares anc caches SQL statement
 
  //############################################################################ 
 
  function prepareStatement($stmt_s)
 
  {
 
    // Check if statement is already in cache
 
    if(isset(self::$stmts[$stmt_s]))
 
    {
 
      return self::$stmts[$stmt_s];
 
    }
 
   
 
    // Prepare stement, store in cache and return
 
    $stmt_handle = self::$DB->prepare($stmt_s);
 
    self::$stmts[$stmt_s] = $stmt_handle;
 
    return $stmt_handle;
 
  }
 
 
 
  //############################################################################
 
  // doStatement: runs SQL statement
 
  //############################################################################ 
 
  protected function doStatement($stmt_s, $values_a)
 
  {
 
    $sth = $this->prepareStatement($stmt_s);
 
   
 
    // Closes the cursor, enabling the statement to be executed again.
 
    $sth->closeCursor();
 
   
 
    // Runs the statement
 
    $db_result = $sth->execute($values_a);
 
    return $sth;
 
  }
 
}
 
</pre>
 
 
 
Next, our ManagerMessage class:
 
 
 
<pre>
 
require_once("Manager.php");
 
 
 
//############################################################################
 
// ManagerMessage class
 
//############################################################################
 
class ManagerMessage extends Manager
 
{
 
  static $add_message = "INSERT INTO messages(title,message,date_added) values(?,?,?)";
 
  static $list_messages = "SELECT id,title,message,date_added FROM messages ORDER BY date_added DESC";
 
  static $search_messages = "SELECT id,title,message,date_added FROM messages WHERE title LIKE ? ORDER BY date_added DESC";
 
  static $delete_message = "DELETE FROM messages WHERE id = ?";
 
 
 
  //############################################################################
 
  // addMessage: adds a message to the database
 
  //############################################################################
 
  function addMessage($title, $message)
 
  {
 
    $values = array($title, $message, date("Y/m/d H:i:s"));
 
    $this->doStatement(self::$add_message, $values);
 
  }
 
 
 
  //############################################################################
 
  // getAllMessages: selects all messages from the database
 
  //############################################################################
 
  function getAllMessages()
 
  {
 
    $stmt = $this->doStatement(self::$list_messages, null);
 
    $result = $stmt->fetchAll();
 
    return $result;
 
  }
 
 
 
  //############################################################################
 
  // searchMessages: searches for a message
 
  //############################################################################
 
  function searchMessages($keywords)
 
  {
 
    $values = array($keywords);
 
    $stmt = $this->doStatement(self::$search_messages, $values);
 
    $result = $stmt->fetchAll();
 
    return $result;
 
  }
 
 
 
  //############################################################################
 
  // deleteMessage: deletes a message
 
  //############################################################################
 
  function deleteMessage($id)
 
  {
 
    $values = array($id);
 
    $stmt = $this->doStatement(self::$delete_message, $values);
 
  } 
 
 
 
}
 
<pre>
 
 
 
Now we can implement the doExecute function in Command_BlogIndex, so it call our database classes:
 
 
 
<pre>
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    // Create manager object
 
    $manager = new ManagerMessage();
 
   
 
    // Are we searching?
 
    $keywords = trim($request->getProperty('search'));
 
   
 
    if($keywords=="")
 
      $data = $manager->getAllMessages();
 
    else
 
      $data = $manager->searchMessages($keywords);
 
     
 
    print_r($data);
 
  }
 
</pre>
 
 
 
=== Checkpoint ===
 
 
 
Your website should now be displaying the data from the database in the form an an array:
 
 
 
Array ( [0] => Array ( [id] => 18 [0] => 18 [title] => Test 2 [1] => Test 2 [message] => Hiya [2] => Hiya [date_added] => 2009-07-27 15:06:38 [3] => 2009-07-27 15:06:38 ) [1] => Array ( [id] => 17 [0] => 17 [title] => Test 1 [1] => Test 1 [message] => Hello world! [2] => Hello world! [date_added] => 2009-07-27 15:06:29 [3] => 2009-07-27 15:06:29 ) )
 
 
 
== Step 5 - Create our first view ==
 
 
 
All we need now is to pass the data above to a view.
 
Let's create all our views in a "views" sub-folder.
 
 
 
<pre>
 
<?require_once("view_helper.php");?>
 
 
 
<?ViewHelper::DisplayHeader("Blog index");?>
 
 
 
<h1>Blog index</h1>
 
 
 
<p>You can <a href="index.php?cmd=BlogAddForm">add messages</a> !</p>
 
 
 
<form action="index.php" method="post">
 
  Search: <input name="search">
 
  <input type="submit" value="Search!">
 
</form>
 
 
 
<?
 
  foreach($data as $message)
 
    echo("<div class=\"message\">
 
            <h2>{$message['title']}</h2>
 
            <p>{$message['message']}</p>
 
            <a href=\"index.php?cmd=BlogDelete&id={$message['id']}\">Delete this message</a>
 
          </div>");
 
?>
 
 
 
<?ViewHelper::DisplayFooter();?>
 
</pre>
 
 
 
As you can see, we have chosen to use a helper:
 
 
 
<pre>
 
//############################################################################
 
// ViewHelper
 
//############################################################################
 
class ViewHelper
 
{
 
  //############################################################################
 
  // Displays HTML Header
 
  //############################################################################
 
  static function DisplayHeader($pageTitle = "")
 
  {
 
    echo("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
 
    echo("<html>");
 
    echo("  <head>");
 
    echo("    <title>{$pageTitle}</title>");
 
    echo("    <link type=\"text/css\" href=\"views/style.css\" rel=\"stylesheet\">");
 
    echo("  </head>");
 
    echo("  <body>");
 
  }
 
 
 
  //############################################################################
 
  // Displays HTML Footer
 
  //############################################################################ 
 
  static function DisplayFooter()
 
  {
 
    echo("  </body>");
 
    echo("</html>"); 
 
  }
 
}
 
</pre>
 
 
 
All you need now is to include your view from your command:
 
 
 
<pre>
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    // Create manager object
 
    $manager = new ManagerMessage();
 
   
 
    // Are we searching?
 
    $keywords = trim($request->getProperty('search'));
 
   
 
    if($keywords=="")
 
      $data = $manager->getAllMessages();
 
    else
 
      $data = $manager->searchMessages($keywords);
 
     
 
    // Include view
 
    include("views/index.php");
 
  }
 
</pre>
 
 
 
=== Checkpoint ===
 
 
 
The home page of your blog should now be working:
 
 
 
[[Image:blog.gif]]
 
 
 
== Step 6 - Adding messages ==
 
 
 
<pre>
 
//############################################################################
 
// SearchVenueCommand class
 
//############################################################################
 
class Command_BlogAddForm extends Command
 
{
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    // Include view
 
    include("views/add_form.php");
 
  }
 
}
 
</pre>
 
 
 
<pre>
 
<?require_once("view_helper.php");?>
 
 
 
<?ViewHelper::DisplayHeader("Add message");?>
 
 
 
<h1>Blog add form</h1>
 
 
 
<p>Please fill in the fields</p>
 
 
 
<form action="index.php?cmd=BlogAdd" method="post">
 
  Title:<br><input name="title">
 
  <br>
 
  Message:<br><textarea name="message"></textarea>
 
  <br>
 
  <input type="submit" value="Add">
 
</form>
 
   
 
<?ViewHelper::DisplayFooter();?>
 
</pre>
 
 
 
<pre>
 
//############################################################################
 
// Command_BlogAdd class
 
//############################################################################
 
class Command_BlogAdd extends Command
 
{
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    // Get data from request
 
    $title = $request->getProperty('title');
 
    $message = $request->getProperty('message');
 
   
 
    // Create manager object
 
    $manager = new ManagerMessage();   
 
   
 
    // Add to database
 
    $manager->addMessage($title, $message);
 
   
 
    // Redirect to index
 
    header("location:index.php");
 
  }
 
}
 
</pre>
 
 
 
== Step 7 - Deleting messages ==
 
 
 
<pre>
 
//############################################################################
 
// SearchVenueCommand class
 
//############################################################################
 
class Command_BlogDelete extends Command
 
{
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    // Get data from request
 
    $id = $request->getProperty('id');
 
   
 
    // Create manager object
 
    $manager = new ManagerMessage();   
 
   
 
    // Add to database
 
    $manager->deleteMessage($id);
 
   
 
    // Redirect to index
 
    header("location:index.php");
 
  }
 
}
 
</pre>
 
 
 
== Step 8 - Searching for message ==
 
 
 
You can do this one :)
 

Latest revision as of 14:57, 22 September 2011

Main Page >> Advanced Web Technologies >> Workbook >> Week 04

Your job today is to implement a blog similar to this one:

The different steps are:

  1. Step 1 - Create and populate database
  2. Step 2 - Create the index.php file, front controller and registry class
  3. Step 3 - Handling user request and creating appropriate command
  4. Step 4 - Accessing the database
  5. Step 5 - Creating our first view
  6. Step 6 - Adding messages
  7. Step 7 - Deleting messages

Let's take it one step at a time... and remember: read and understand the code before pasting it into your text editor!