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
Objectives
Applied
1. Use the MVC pattern to develop your web applications.
2. Create and use functions that do the database processing for the
model of your MVC applications.
3. Use the built-in header function to redirect HTTP requests.
Knowledge
1. Describe the Model-View-Controller pattern.
2. Explain how the MVC pattern can improve application
development.
3. In general terms, describe the code for creating and calling a
function.
4. Distinguish between forwarding an HTTP request and redirecting
a request.
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 2
The MVC pattern
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 3
Recall: The syntax for creating an object from any
class
new ClassName(arguments);
The syntax for creating a database object
from the PDO class
new PDO($dsn, $username, $password);
The syntax for a DSN (Data Source Name)
for a MySQL database
mysql:host=host_address;dbname=database_name
How to connect to a MySQL database
$dsn = 'mysql:host=localhost;dbname=abc1234';
$username = 'abc1234'; //your username
$password = 'xxxxxx'; //your sql password
// creates PDO object
$db = new PDO($dsn, $username, $password);
Murach's PHP and MySQL, C4 © 2010, Mike Murach & Associates, Inc. Slide 4
The syntax for executing a method of any object
$objectName->methodName(argumentList)
A method of the PDO class for executing a
SELECT statement
query($select_statement)
The syntax for executing the query method
of the database object
$PDO_object->query($select_statement)
Murach's PHP and MySQL, C4 © 2010, Mike Murach & Associates, Inc. Slide 5
A query method with the SELECT statement
in a variable
$query = 'SELECT * FROM products
WHERE categoryID = 1
ORDER BY productID';
$products = $db->query($query);
A query method with the SELECT statement
as the argument
$products = $db->query('SELECT * FROM products');
Murach's PHP and MySQL, C4 © 2010, Mike Murach & Associates, Inc. Slide 6
A method of the PDO class
for modifying the database : INSERT, UPDATE,
DELETE
exec($sql_statement)//returns the number of rows affected
How to execute an INSERT statement
$category_id = 1;
$code = 'strat';
$name = 'Fender Stratocaster';
$price = 699.99;
$query = "INSERT INTO products
(categoryID, productCode, productName, listPrice)
VALUES
($category_id, '$code', '$name', $price)";
$insert_count = $db->exec($query);
Murach's PHP and MySQL, C4 © 2010, Mike Murach & Associates, Inc. Slide 7
How to execute an UPDATE statement
$product_id = 4;
$price = 599.99;
$query = "UPDATE products
SET listPrice = $price
WHERE productID = $product_id";
$update_count = $db->exec($query);
How to execute a DELETE statement
$product_id = 4;
$query = "DELETE FROM products
WHERE productID = $product_id";
$delete_count = $db->exec($query);
Murach's PHP and MySQL, C4 © 2010, Mike Murach & Associates, Inc. Slide 8
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 9
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 10
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 11
Recall from Chapter 2: forwarding a request
The include function
include 'index.php'; // parentheses are optional
include('index.php'); // index.php in the current
// directory
The require function
require('index.php'); // index.php in the current
// directory
The exit function
exit; // parentheses are optional
exit();
exit('Unable to connect to DB.');
// passes a message to the browser
Murach's PHP and MySQL, C2 © 2010, Mike Murach & Associates, Inc. Slide 12
How to pass control to another PHP file in the
current directory
if ($is_valid) {
include('process_data.php');
exit();
}
How to navigate up and down directories
include('view/header.php'); // down one directory
include('./error.php'); // in the current directory
include('../error.php'); // up one directory
include('../../error.php'); // up two directories
Murach's PHP and MySQL, C2 © 2010, Mike Murach & Associates, Inc. Slide 13
A PHP function for redirecting a request
header($header) //send an HTTP header to the browser
The header function
header('Location: .'); // the current directory
header('Location: ..'); // up one directory
header('Location: ./admin'); // down one directory
header('Location: error.php');
header('Location: http://www.murach.com/');
How to redirect a request
if ($action == 'delete') {
$product_id = $_POST['product_id'];
delete_product($product_id);
header('Location: .');
//redirect to the default file of the current directory
}
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 14
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 15
Terms
forward a request : include, require, exit, die. All processing takes
place on the server
redirect a request: header. The server returns a response that tells the
browser to request another URL
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 16
The Product List page: The user interface
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 17
The Add Product page: The user interface
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 18
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 19
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 20
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 21
The Controller: product_manager/index.php
<?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 22
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 23
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 24
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 25
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 26
The view: footer.php file
<div id="footer">
<p>
© <?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 27
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 28
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> </th>
</tr>
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 29
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 30
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 31
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 32
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> </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 33
The Product List page
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 34
The Product page
Murach's PHP and MySQL, C5 © 2010, Mike Murach & Associates, Inc. Slide 35
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 36
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 37
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 38
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 39
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 40
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 41
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 42
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 43
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 44