|
|
(73 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 |
| | | |
− | == 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] |
| | | |
− | <pre>
| + | The different steps are: |
− | CREATE TABLE IF NOT EXISTS `messages` (
| |
− | `id` int(11) NOT NULL auto_increment,
| |
− | `title` varchar(255) NOT NULL,
| |
− | `message` text NOT NULL,
| |
− | `date_added` datetime NOT NULL,
| |
− | PRIMARY KEY (`id`)
| |
− | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=19 ;
| |
| | | |
− | INSERT INTO `messages` (`id`, `title`, `message`, `date_added`) VALUES
| + | # [[DesignPatternStep1|Step 1]] - Create and populate database |
− | (1, 'Test 1', 'Hello world!', '2009-07-27 15:06:29'),
| + | # [[DesignPatternStep2|Step 2]] - Create the index.php file, front controller and registry class |
− | (2, 'Test 2', 'Hiya', '2009-07-27 15:06:38');
| + | # [[DesignPatternStep3|Step 3]] - Handling user request and creating appropriate command |
− | </pre>
| + | # [[DesignPatternStep4|Step 4]] - Accessing the database |
| + | # [[DesignPatternStep5|Step 5]] - Creating our first view |
| + | # [[DesignPatternStep6|Step 6]] - Adding messages |
| + | # [[DesignPatternStep7|Step 7]] - Deleting messages |
| | | |
− | == Create index.php file ==
| + | Let's take it one step at a time... and remember: read and understand the code before pasting it into your text editor! |
− | | |
− | <pre>
| |
− | // The index simply calls the front controller
| |
− | require("Controller.php");
| |
− | Controller::run();
| |
− | </pre>
| |
− | | |
− | == 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>
| |
− | | |
− | == Create 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 1 ==
| |
− | | |
− | Your page should display "Hello world!"
| |
− | | |
− | == Create 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>
| |
− | | |
− | == Create 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>
| |
− | | |
− | == Create 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>
| |
− | | |
− | == Create Command_BlogIndex class ==
| |
− | | |
− | <pre>
| |
− | //############################################################################
| |
− | // SearchVenueCommand class
| |
− | //############################################################################
| |
− | class Command_BlogIndex extends Command
| |
− | {
| |
− | //############################################################################
| |
− | // doExecute
| |
− | //############################################################################
| |
− | function doExecute(Request $request)
| |
− | {
| |
− | print("Blog Index command");
| |
− | }
| |
− | }
| |
− | </pre>
| |
− | | |
− | == Update Controller class ==
| |
− | | |
− | 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 2 ==
| |
− | | |
− | Your website should now display "Blog Index command".
| |
− | | |
− | == Create 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>
| |
− | | |
− | == Create 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>
| |
− | | |
− | == Implement doExecute function in Command_BlogIndex class ==
| |
− | | |
− | <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 3 ==
| |
− | | |
− | 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 ) )
| |