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

From mi-linux
Jump to navigationJump to search
Line 18: Line 18:
  
  
== Step 4 - Accessing the database ==
 
 
And by “doing stuff”, we obviously mean “get data from the database”!
 
 
First let's create our Manager class. It contains all the core database functionality: connecting to the server, parsing SQL queries, that sort of things.
 
 
It is defined as “abstract”, because it is not meant to be used directly. It serves as a base for more specialized Manager classes to be built on.
 
 
Anyway, here is the code:
 
 
<pre>
 
// Manager.php
 
 
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, let’s create our Manager class responsible for handling our blog messages. It is called ManagerMessage and “extends” our standard Manager class. It defines the SQL queries needed to handle messages, and adds functions such as getAllMessages and addMessage.
 
 
The code:
 
 
<pre>
 
// ManagerMessage.php
 
 
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 our command (Command_BlogIndex), so it calls our newly written ManagerMessage class:
 
 
<pre>
 
// Command_BlogIndex.php
 
 
  //############################################################################
 
  // doExecute
 
  //############################################################################
 
  function doExecute(Request $request)
 
  {
 
    // Create manager object
 
    $manager = new ManagerMessage();
 
 
    // Get data from database object
 
    $data = $manager->getAllMessages();
 
     
 
    // Dump data array to screen
 
    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 ) )
 
 
We're nearly there!
 
  
 
== Step 5 - Creating our first view ==
 
== Step 5 - Creating our first view ==

Revision as of 16:44, 12 July 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!



Step 5 - Creating 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.

<!-- views/index.php -->

<?require_once("ViewHelper.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();?>

The code itself it pretty simple. It loops through the data array using a foreach statement.

Note that instead of duplication the <HEAD> section in all our views, we have decided to move it to a helper function. All our views can then include the helper file and call the DisplayHeader and DisplayFooter function:

// views/ViewHelper.php

//############################################################################
// 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>"); 
 }
}

All you need now is to include your view from your command:

// Command_BlogIndex.php

 //############################################################################
 // doExecute
 //############################################################################ 
 function doExecute(Request $request)
 {
 // Create manager object
 $manager = new ManagerMessage();

 // Get data from database object
 $data = $manager->getAllMessages();
 
 // Include view
 include("views/index.php");
 }

Note: I'll let you create your own style sheet, mine is boring anyway :)

Checkpoint

The home page of your blog should now be working!!!

Image:blog.gif

Step 6 - Adding messages

Next, let’s add a command to add blog messages. You might have noticed above that our “add messages” link (see above) points to “index.php?cmd=BlogAddForm”

So first, you need a new command called “Command_BlogAddForm”. It doesn’t do much, it simply displays the view containing the form. Here is the code:

// Command_BlogAddForm.php

//############################################################################
// SearchVenueCommand class
//############################################################################
class Command_BlogAddForm extends Command
{
  //############################################################################
  // doExecute
  //############################################################################ 
  function doExecute(Request $request)
  {
    // Include view
    include("views/add_form.php");
  }
}

And here is the view containing the form:

<!-- views/add_form.php -->

<?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();?>

Again note that the "action" attribute of the <FORM> above points to "index.php?cmd=BlogAdd". So we need another action responsible for reading the user data from the form, and creating a new record in the database... here it is!

// Command_BlogAdd.php

//############################################################################
// 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");
  }
}

Note: This action doesn't have a view. It simply redirects the user to the index of the forum.

Checkpoint

You should now be able to add new messages... try it!

Step 7 - Deleting messages

Finally, let’s create a new action in charge of message deletion.

Again if you browse the mouse over the “delete this message” links, you will see URLs such as “index.php?cmd=BlogDelete&id=19”

So we need a new Command_BlogDelete class. Here is the code:

// Command_BlogDelete.php

//############################################################################
// 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");
  }
}

Nothing too complicated here...

Checkpoint

You should now be able to delete messages.

Note: It is always better practice to ask users to confirm deletion first... but you can do that bit ;)