Chapter 5 How to use the MVC pattern to organize your code Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 1

Download Report

Transcript Chapter 5 How to use the MVC pattern to organize your code Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 1

Chapter 5
How to use
the MVC pattern
to organize your code
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 1
Organizing the code for a software project
A large software project is easier to design, build and
maintain if it can be organized a separate
components
There are several approaches to such organization;
O-O, IPO, and MVC are some examples
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 2
MVC – A definition from Wikipedia
Model–view–controller (MVC) is a software
architecture pattern which separates the
representation of information from the user's
interaction with it.
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 3
MVC – The Pieces
The model consists of application data, business
rules, logic, and functions.
A view can be any output representation of data,
such as a chart or a diagram. Multiple views of the
same data are possible, such as a bar chart for
management and a tabular view for accountants.
The controller mediates input, converting it to
commands for the model or view.
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 4
The MVC pattern
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 5
The Product List page
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 6
The Add Product page
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 7
The index.php file from Ch 4
<?php
require_once('database.php');
// Get category ID
if(!isset($category_id)) {
$category_id = $_GET['category_id'];
if (!isset($category_id)) {
$category_id = 1;
}
}
// Get name for current category
$query = "SELECT * FROM categories
WHERE categoryID = $category_id";
$category = $db->query($query);
$category = $category->fetch();
$category_name = $category['categoryName'];
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 8
The index.php file (continued)
// Get all categories
$query = 'SELECT * FROM categories
ORDER BY categoryID';
$categories = $db->query($query);
// Get products for selected category
$query = "SELECT * FROM products
WHERE categoryID = $category_id
ORDER BY productID";
$products = $db->query($query);
?>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 9
The index.php file (continued)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- the head section -->
<head>
<title>My Guitar Shop</title>
<link rel="stylesheet" type="text/css"
href="main.css" />
</head>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 10
The index.php file (continued)
<body>
<div id="page">
<div id="header">
<h1>Product Manager</h1>
</div>
<div id="main">
<h1>Product List</h1>
<div id="sidebar">
<!-- display a drop-down list of categories -->
<h2>Categories</h2>
<ul class="nav">
<?php foreach ($categories as $category) : ?>
<li>
<a href="?category_id=
<?php echo $category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 11
The index.php file (continued)
<div id="content">
<!-- display a table of products -->
<h2><?php echo $category_name; ?></h2>
<table>
<tr>
<th>Code</th>
<th>Name</th>
<th class="right">Price</th>
<th>&nbsp;</th>
</tr>
<?php foreach ($products as $product) : ?>
<tr>
<td><?php echo
$product['productCode']; ?></td>
<td><?php echo $product['productName'];
?></td>
<td class="right"><?php echo
$product['listPrice']; ?></td>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 12
The index.php file (continued)
<td><form action="delete_product.php"
method="post"
id="delete_product_form">
<input type="hidden"
name="product_id"
value="<?php echo
$product['productID']; ?>" />
<input type="hidden"
name="category_id"
value="<?php echo
$product['categoryID']; ?>" />
<input type="submit"
value="Delete" />
</form></td>
</tr>
<?php endforeach; ?>
</table>
<p><a href="add_product_form.php">
Add Product</a></p>
</div>
</div>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 13
The index.php file (continued)
<div id="footer">
<p>&copy; <?php echo date("Y"); ?>
My Guitar Shop, Inc.</p>
</div>
</div><!-- end page -->
</body>
</html>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 14
The delete_product.php file from Ch 4
<?php
// Get IDs
$product_id = $_POST['product_id'];
$category_id = $_POST['category_id'];
// Delete the product from the database
require_once('database.php');
$query = "DELETE FROM products
WHERE productID = '$product_id'";
$db->exec($query);
// Display the Product List page
include('index.php');
?>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 15
The add_product_form.php file from Ch 4
<?php
require_once('database.php');
$query = 'SELECT *
FROM categories
ORDER BY categoryID';
$categories = $db->query($query);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- the head section -->
<head>
<title>My Guitar Shop</title>
<link rel="stylesheet" type="text/css"
href="main.css" />
</head>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 16
The add_product_form.php file (continued)
<!-- the body section -->
<body>
<div id="page">
<div id="header">
<h1>Product Manager</h1>
</div>
<div id="main">
<h1>Add Product</h1>
<form action="add_product.php" method="post"
id="add_product_form" >
<label>Category:</label>
<select name="category_id">
<?php foreach ($categories as $category) : ?>
<option value="<?php echo
$category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</option>
<?php endforeach; ?>
</select><br />
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 17
The add_product_form.php file (continued)
<label>Code:</label>
<input type="input" name="code" />
<br />
<label>Name:</label>
<input type="input" name="name" />
<br />
<label>List Price:</label>
<input type="input" name="price" />
<br />
<label>&nbsp;</label>
<input type="submit" value="Add Product" />
<br />
</form>
<p><a href="index.php">View Product List</a></p>
</div><!-- end main -->
</div><!-- end page -->
</body>
</html>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 18
The add_product.php file
<?php
// Get the product data
$category_id = $_POST['category_id'];
$code = $_POST['code'];
$name = $_POST['name'];
$price = $_POST['price'];
// Validate inputs
if (empty($code) || empty($name) || empty($price) ) {
$error = "Invalid product data. Try again.";
include('error.php');
} else {
// If valid, add the product to the database
require_once('database.php');
$query = "INSERT INTO products
(categoryID, productCode, productName, listPrice)
VALUES
('$category_id', '$code', '$name', '$price')";
$db->exec($query);
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 19
The add_product.php file (continued)
// Display the Product List page
include('index.php');
}
?>
Murach's PHP and MySQL, C4
© 2010, Mike Murach & Associates, Inc.
Slide 20
We will refactor this application using MVC
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 21
Review of the syntax for coding a function
function function_name([parameter_list]) {
// statements that are executed by the function
}
A function with no parameters that returns a
PDOStatement object
function get_products() {
global $db;
$query = 'SELECT * FROM products';
$products = $db->query($query);
return $products;
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 22
A function with one parameter that deletes a
product row and returns a count
function delete_product($product_id) {
global $db;
$query = "DELETE FROM products
WHERE productID = '$product_id'";
$row_count = $db->exec($query);
return $row_count;
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 23
A function with four parameters that adds a
product to a database table
function add_product($category_id, $name, $description,
$price) {
global $db;
$query = "INSERT INTO products
(categoryID, productCode, productName, listPrice)
VALUES
('$category_id', '$code', '$name', '$price')";
$row_count = $db->exec($query);
return $row_count;
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 24
A function call with no arguments
and a returned PDOStatement object
$products = get_products();
A function call with one argument
and a returned row count
$row_count = delete_product($product_id);
A function call with four arguments
and a returned row count
$row_count = add_product($category_id, $name,
$description, $price);
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 25
A PHP function for redirecting a request
header($header)
The header function
header('Location:
header('Location:
header('Location:
header('Location:
header('Location:
.');
// the current directory
..');
// up one directory
./admin');
// down one directory
error.php');
http://www.murach.com/');
How to redirect a request
if ($action == 'delete') {
$product_id = $_POST['product_id'];
delete_product($product_id);
header('Location: .');
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 26
How to redirect a request
that includes a parameter
if ($action == 'delete') {
$product_id = $_POST['product_id'];
$category_id = $_POST['category_id'];
delete_product($product_id);
header("Location: .?category_id=$category_id");
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 27
The Product List page
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 28
The Add Product page
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 29
The MVC pattern
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 30
The model/category_db.php file
<?php
function get_categories() {
global $db;
$query = 'SELECT *
FROM categories
ORDER BY categoryID';
$result = $db->query($query);
return $result;
}
function get_category_name($category_id) {
global $db;
$query = "SELECT *
FROM categories
WHERE categoryID = $category_id";
$category = $db->query($query);
$category = $category->fetch();
$category_name = $category['categoryName'];
return $category_name;
}
?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 31
The model/product_db.php file
<?php
function get_products_by_category($category_id) {
global $db;
$query = "SELECT * FROM products
WHERE products.categoryID = '$category_id'
ORDER BY productID";
$products = $db->query($query);
return $products;
}
function get_product($product_id) {
global $db;
$query = "SELECT * FROM products
WHERE productID = '$product_id'";
$product = $db->query($query);
$product = $product->fetch();
return $product;
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 32
The model/product_db.php file (continued)
function delete_product($product_id) {
global $db;
$query = "DELETE FROM products
WHERE productID = '$product_id'";
$db->exec($query);
}
function add_product($category_id, $code, $name, $price) {
global $db;
$query = "INSERT INTO products
(categoryID, productCode, productName, listPrice)
VALUES
('$category_id', '$code', '$name', '$price')";
$db->exec($query);
}
?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 33
product_manager/index.php (the controller)
<?php
require('../model/database.php');
require('../model/product_db.php');
require('../model/category_db.php');
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else if (isset($_GET['action'])) {
$action = $_GET['action'];
} else {
$action = 'list_products';
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 34
The controller (continued)
if ($action == 'list_products') {
// Get the current category ID
$category_id = $_GET['category_id'];
if (!isset($category_id)) {
$category_id = 1;
}
// Get the product and category data
$category_name = get_category_name($category_id);
$categories = get_categories();
$products = get_products_by_category($category_id);
// Display the product list
include('product_list.php');
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 35
The controller (continued)
} else if ($action == 'delete_product') {
// Get the IDs and delete the product
$product_id = $_POST['product_id'];
$category_id = $_POST['category_id'];
delete_product($product_id);
// Display the Product List page
// for the current category
header("Location: .?category_id=$category_id");
} else if ($action == 'show_add_form') {
$categories = get_categories();
include('product_add.php');
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 36
The controller (continued)
} else if ($action == 'add_product') {
$category_id = $_POST['category_id'];
$code = $_POST['code'];
$name = $_POST['name'];
$price = $_POST['price'];
if (empty($code) || empty($name) || empty($price)) {
$error = "Invalid product data.
Check all fields and try again.";
include('../errors/error.php');
} else {
add_product($category_id, $code, $name, $price);
// Display the Product List page
// for the current category
header("Location: .?category_id=$category_id");
}
}
?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 37
The view/header.php file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- the head section -->
<head>
<title>My Guitar Shop</title>
<link rel="stylesheet" type="text/css"
href="/book_apps/ch05_guitar_shop/main.css" />
</head>
<!-- the body section -->
<body>
<div id="page">
<div id="header">
<h1>My Guitar Shop</h1>
</div>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 38
The view/footer.php file
<div id="footer">
<p>
&copy; <?php echo date("Y"); ?>
My Guitar Shop, Inc.
</p>
</div>
</div><!-- end page -->
</body>
</html>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 39
product_manager/product_list.php (a view)
<?php include '../view/header.php'; ?>
<div id="main">
<h1>Product List</h1>
<div id="sidebar">
<!-- display a list of categories -->
<h2>Categories</h2>
<ul class="nav">
<?php foreach ($categories as $category) : ?>
<li>
<a href="?category_id=<?php
echo $category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 40
product_manager/product_list.php (cont.)
<div id="content">
<!-- display a table of products -->
<h2><?php echo $category_name; ?></h2>
<table>
<tr>
<th>Code</th>
<th>Name</th>
<th class="right">Price</th>
<th>&nbsp;</th>
</tr>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 41
product_manager/product_list.php (cont.)
<?php foreach ($products as $product) : ?>
<tr>
<td><?php echo
$product['productCode']; ?></td>
<td><?php echo
$product['productName']; ?></td>
<td class="right"><?php echo
$product['listPrice']; ?></td>
<td><form action="." method="post">
<input type="hidden" name="action"
value="delete_product" />
<input type="hidden" name="product_id"
value="<?php echo
$product['productID']; ?>" />
<input type="hidden" name="category_id"
value="<?php echo
$product['categoryID']; ?>" />
<input type="submit" value="Delete" />
</form></td>
</tr>
<?php endforeach; ?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 42
product_manager/product_list.php (cont.)
</table>
<p><a href="?action=show_add_form">
Add Product</a></p>
</div>
</div>
<?php include '../view/footer.php'; ?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 43
product_manager/product_add.php
<?php include '../view/header.php'; ?>
<div id="main">
<h1>Add Product</h1>
<form action="index.php" method="post"
id="add_product_form">
<input type="hidden" name="action"
value="add_product" />
<label>Category:</label>
<select name="category_id">
<?php foreach ( $categories as $category ) : ?>
<option value="<?php echo
$category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</option>
<?php endforeach; ?>
</select>
<br />
<label>Code:</label>
<input type="input" name="code" /><br />
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 44
product_manager/product_add.php (cont.)
<label>Name:</label>
<input type="input" name="name" />
<br />
<label>List Price:</label>
<input type="input" name="price" />
<br />
<label>&nbsp;</label>
<input type="submit" value="Add Product" />
<br />
</form>
<p><a href="index.php?action=list_products">
View Product List</a></p>
</div>
<?php include '../view/footer.php'; ?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 45
Another Application – A Consumer Catalog
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 46
The Product List page
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 47
The Product page
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 48
The product_catalog/index.php file (the controller)
<?php
require('../model/database.php');
require('../model/product_db.php');
require('../model/category_db.php');
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else if (isset($_GET['action'])) {
$action = $_GET['action'];
} else {
$action = 'list_products';
}
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 49
The controller (continued)
if ($action == 'list_products') {
$category_id = $_GET['category_id'];
if (empty($category_id)) {
$category_id = 1;
}
$categories = get_categories();
$category_name = get_category_name($category_id);
$products = get_products_by_category($category_id);
include('product_list.php');
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 50
The controller (continued)
} else if ($action == 'view_product') {
$categories = get_categories();
$product_id = $_GET['product_id'];
$product = get_product($product_id);
// Get product data
$code = $product['productCode'];
$name = $product['productName'];
$list_price = $product['listPrice'];
// Set the discount percent (for all web orders)
$discount_percent = 30;
// Calculate discounts
$discount_amount =
round($list_price * ($discount_percent / 100.0), 2);
$unit_price = $list_price - $discount_amount;
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 51
The controller (continued)
// Format the calculations
$discount_amount = number_format($discount_amount, 2);
$unit_price = number_format($unit_price, 2);
// Get image URL and alternate text
$image_filename = '../images/' . $code . '.png';
$image_alt = 'Image: ' . $code . '.png';
include('product_view.php');
}
?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 52
The product_catalog/product_list.php file (a view)
<?php include '../view/header.php'; ?>
<div id="main">
<div id="sidebar">
<h1>Categories</h1>
<ul class="nav">
<!-- display links for all categories -->
<?php foreach($categories as $category) : ?>
<li>
<a href="?category_id=<?php echo
$category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 53
The product_catalog/product_list.php file (cont.)
<div id="content">
<h1><?php echo $category_name; ?></h1>
<ul class="nav">
<?php foreach ($products as $product) : ?>
<li>
<a href="?action=view_product&product_id=
<?php echo $product['productID']; ?>">
<?php echo $product['productName']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php include '../view/footer.php'; ?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 54
The product_catalog/product_view.php file
<?php include '../view/header.php'; ?>
<div id="main">
<div id="sidebar">
<h1>Categories</h1>
<ul class="nav">
<!-- display links for all categories -->
<?php foreach($categories as $category) : ?>
<li>
<a href="?category_id=<?php echo
$category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 55
The product_catalog/product_view.php file (cont.)
<div id="content">
<h1><?php echo $name; ?></h1>
<div id="left_column">
<p>
<img src="<?php echo $image_filename; ?>"
alt="Image: <?php echo $image_alt; ?>" />
</p>
</div>
<div id="right_column">
<p><b>List Price:</b>
$<?php echo $list_price; ?></p>
<p><b>Discount:</b> <?php echo
$discount_percent; ?>%</p>
<p><b>Your Price:</b>
$<?php echo $unit_price; ?>
(You save $<?php echo $discount_amount;
?>)</p>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 56
The product_catalog/product_view.php file (cont.)
<form action="<?php echo '../cart' ?>"
method="post">
<input type="hidden" name="action"
value="add" />
<input type="hidden" name="product_id"
value="<?php echo $product_id; ?>" />
<b>Quantity:</b>
<input type="text" name="quantity" value="1"
size="2" />
<input type="submit" value="Add to Cart" />
</form>
</div>
</div>
</div>
<?php include '../view/footer.php'; ?>
Murach's PHP and MySQL, C5
© 2010, Mike Murach & Associates, Inc.
Slide 57