What We Will Cover
Elucidations
Homework Questions?
Quiz Questions?
^ top
10.1: Object-Oriented PHP
Objectives
At the end of the lesson the student will be able to:
- Write code that defines a class
- Create objects from classes
- Use objects in programs
|
^ top
10.1.1: About Classes and Objects
The What and Why of Classes and Objects
- Object-oriented programming (OOP) was developed to solve problems with large programming projects
- Since it was so useful, OOP has become a part of most programming languages
- More and more people are writing PHP programs using OOP
- You need to learn OOP to understand and apply its benefits to your programs
- No matter the size of your project, using OOP can improve your code
- In large programming projects, code develops secret alliances
- For instance, the login code may share a database connection with the credit card processing code
- Such an alliance, or tight coupling, may make sense when originally written
- However, such alliances make it difficult when you need to make changes
- To reduce the alliances, you use encapsulation and data hiding, two of the key parts of OOP
Encapsulation
Data Hiding
The Difference Between Classes and Objects
- Classes are the code used to define an object
- Classes define member variables and functions that make up an object
- An object is an "instance of" a class
- Each object has its own location in memory to store the member variables
- By analogy, a class is like a design of a car or other object
- You need to build the object from the design before you can use the object
^ top
10.1.2: Defining a Class
- A class is like a container with variables and functions inside it
- Contains variables that should be used only within the object
- Contains functions to perform the actions of the object
- Syntax for coding a class:
class ClassName {
var $classVariable;
function classFunction($arg1, $arg2, ...) {
// do something
}
}
Example of a Class
- Note the differences in the following code:
<?php
// Define a class for tracking users
class User {
// Class variables
var $name, $password, $lastLogin;
// Constructor
function User($name, $password) {
$this->name = $name;
$this->password = $password;
$this->lastLogin = time();
}
// Get the date of the last login
function getLastLogin() {
return(date("M d Y", $this->lastLogin));
}
}
// Create an instance (an object)
$ed = new User("eparrish", "abc123");
// Get the last login date
print $ed->getLastLogin()."<br>\n" ;
// Print the user's name
print "$ed->name<br>\n";
?>
- Displays the output:
Sep 03 2010
eparrish
Programming Style: Class Naming Conventions
- Use nouns to name classes -- they represent objects
- Start class names with a capital letter
- Capital letter differentiates classes from methods and variables
^ top
10.1.3: Coding Constructors
- One of the important actions of class functions is to manage the object variables
- Unfortunately, PHP 4 does not support data hiding
- However, PHP 5 does support data hiding using the access specifiers:
public, private and protected
- Constructors are called whenever an object is created from a class
- Primary purpose is to initialize the object variables
- Syntax for declaring constructors:
function ClassName($arg1, $arg2, ...) {
// statements to initialize object variables
// other initializing statements as needed
}
Example of a Constructor
// Constructor
function User($name, $password) {
$this->name = $name;
$this->password = $password;
$this->lastLogin = time();
}
- In this example, the constructor initializes three object variables
- Note that constructors have the same name as the class
- Also notice the use of the
$this variable
^ top
10.1.4: Object Members and $this
- Object functions and variables are like any other PHP function and variable
- To call them however, you must use
-> operator
- Every class has a
$this variable that stores the memory reference for the object
- Within the class, you must use the
$this variable to access an object variable or function
$this->name
Outside of the class, you use the $objectName to reference a variable or function
$ed->name
Note that accessing the name variable of the object directly, rather than through a function, is an example of breaking the data hiding
^ top
10.1.5: Creating an Object Using new
- The syntax for creating an object from ("instance of") a class:
$objectName = new ClassName($arg1, $arg2, ...);
For example:
$ed = new User("eparrish", "abc123");
You can trace the program flow through the code of the class:
// Class variables
var $name, $password, $lastLogin;
// Constructor
function User($name, $password) {
$this->name = $name;
$this->password = $password;
$this->lastLogin = time();
}
When the new operator is used, memory space is allocated for the object variables
The call to the constructor function copies the argument values to the parameters:
"eparrish" to $name
"abc123" to $password
Then the parameters are used to initialize the object variables:
$name is assigned to $this->name
$password is assigned to $this->password
Other object variables are initialized as well:
- The current
time() is assigned to $this->lastLogin
One object, an instance of the class, has now been created and initialized
To create a second object in memory:
$joan = new User("jjones", "123abc");
You can create as many objects as you need without the variable or function names clashing
- The object name keeps the namespaces separated
^ top
10.1.6: Summary
- OOP (object-oriented programming) adds the benefit of encapsulation to your reusable code
- All code is encapsulated in one place
- Variables are stored in an object
- Functions are included that work with those variables
- Syntax for coding a class:
class ClassName {
var $classVariable;
function classFunction($arg1, $arg2, ...) {
// do something
}
}
To instantiate an object from a class, you use the new operator
$ed = new User("eparrish", "abc123");
Classes have a special function, called a constructor, to initialize object variables
Constructors are called when the class is created with the new operator
Object functions and variables are like other PHP functions and variables
However, to call them you must use -> operator
Every class has a $this variable that stores the memory reference for the object
Within the class, you must use the $this variable to access an object variable or function
$this->name
Outside of the class, you use the $objectName to reference a variable or function
$ed->name
You can create as many objects as you need for an application
Each object is separate in memory with its own storage space
In the next section we will look at how to use classes and objects to make writing forms easier
^ top
Exercise 10.1
In this exercise we code a PHP class and construct multiple objects.
Specifications
- Start a file named
product.php and save it to the public_html directory.
- Write a definition for a class named
Product that has member variables $name and $description.
- Write a constructor that sets the values of the
$name and $description variables.
- Also code a
show function that displays the Product information in a browser.
- In the same file, but outside the class, write code that creates and displays the information for two
Product objects.
- Submit your
product.php file as part of this weeks exercises.
One possible answer (Try it!)
^ top
10.2: Form Verification
Objectives
At the end of the lesson the student will be able to:
- Apply their knowledge of classes to a design problem
- Use a class to verify form data
|
^ top
10.2.1: Design Specifications
The Problem
- A common programming activity for web developers is creating forms
- There are many problems to overcome when designing a professional form
- One of the problems is to verify the data a user enters
- Failure to build in error checking can cause wrong results or worse
- Checking input for errors is often necessary to ensure
- Required fields are not left blank
- Numbers are within a certain range
- Date values are valid
- Email addresses are valid
- Malicious data was not entered
- Most, but not all entry errors come from text fields
- You can prevent many data entry errors by designing an input form using non-textual elements
- However, not all data can be collected easily without text fields
- Error checking can, and should be, done on the client with JavaScript
- Javascript is beyond the scope of this course
- You can take CIS-132 to learn JavaScript
- However, you still need to verify form data at the server
- Otherwise, People can bypass your error checks
- By disabling JavaScript or by some other means
Form Verification Requirements
- We want a reusable code library that operates as follows:
- The form is displayed and the user fills it in.
- The user submits the form to the server.
- If they left something out or provided invalid input, the form is redisplayed with the data that they already entered.
- The redisplayed form tells the user what is wrong and flags the incorrect fields.
- The application loops until the user fills the form in correctly.
- Also, we want to tailor the error messages to the problem and control how incorrect fields are flagged
- In addition, we would like all our form and validation code on one page
For Example
^ top
10.2.2: Form Page Organization
- Before we go into detail about our form-verification library, let discuss how we would use it
- One of our design objectives is putting all the code for a form on one page
- To accomplish this task, we set the form action to the current page
<form method="POST" action="formtest.php">
To help us process the form correctly, we organize our page using functions
This is very similar to the page organization we used in lesson 9.4.5
Following you can see the structure of a form page organized with functions
Example Page Structure
<?php
ob_start();
require_once("includes/redirect.php");
include_once("includes/formverifier.php");
$title = "Form Page Organization";
main($title);
function main($title = "") {
$f = new FormVerifier();
if (isset($_REQUEST["submit"])) {
$error = checkForm($f);
if (!$error) { // data is OK
saveData($f);
redirect("nextpage.php?it=worked");
}
}
require("includes/header.php");
showContent($title, $f);
require("includes/footer.php");
}
// Check the input form for errors
function checkForm($f) {
// Put test functions here
return $f->isError();
}
// Save the data
function saveData($f) {
// Save the data;
}
function showContent($title, $f) {
?>
<h1><?php echo $title ?></h1>
<?php echo $f->reportErrors() ?>
<form method="POST" action="formtest.php">
<!-- Other form elements here -->
</form>
<?php
}
?>
^ top
10.2.3: Architecture and Inheritance
- Now lets discuss how we build our form-verification library
- We will use classes for our design to gain the benefits of OOP
- Encapsulated data for easier handling and better protection
- Improved reuseability of code in other pages and applications
- Easier maintenance for when you make changes
- Removal of potential namespace clashes
- In brief, we will have the following in our class:
- An array to hold a list of errors encountered during validation
- Other private data variables as needed
- General purpose functions such as constructors
- Functions to handle and report errors
- Functions for use in validating user-supplied data
- Functions for creating various form elements
- Some people may not want to use a class for creating form elements
- To accommodate them, we split our design into two parts
FormVerifier: first 5 items
FormLib: full-featured form library
- The two parts of our design are connected using inheritance
Inheritance
Inheritance: the ability to define new classes from existing ones.
- Inheritance is another feature of object-oriented programming
- It lets you inherit all the variables and functions of another class
- A class that inherits is called the subclass (derived, child)
- A class that is inherited from is called the superclass (base, parent)
- In a subclass, you can define new fields and methods not found in the superclass
- To implement inheritance in PHP, you use the
extends keyword
- So to connect our two classes using inheritance, we use the code:
class FormLib extends FormVerifier
All the data and functions of FormVerifier are included in FormLib
We will add more data variables and functions to FormLib
^ top
10.2.4: Class Design Overview
- The following is the structure of our
FormVerifier class
- We have two "private" variables
$_errorList: stores a list of errors as they are encountered
$_errColor: stores the color we will use to display error messages
- Our constructor sets the value of
$_errColor
- We would call our constructor using something like:
$f = new FormVerifier();
In addition, we will add several functions for error handling and verification
FormVerifier Class Structure
class FormVerifier {
//---- private variables ----
var $_errorList = array();
var $_errColor;
//---- General purpose functions ----
// constructor
function FormVerifier($errColor = "red") {
$this->_errColor = $errColor;
}
//---- Error tracking and reporting functions ----
//---- User input verification ----
}
Getting a Form Value
- One of the basic operations we need is to get value from the form into our PHP code
- For this we can use the
$_REQUEST[] superglobal array
$_REQUEST["submit"]
However, we do not always know if a form value has been set
When form variables are not set, we get warning messages, or even worse, logic errors
Notice: Undefined variable: dbpw in dbentry.php on line 40
To avoid this problem, we test all form variables before using them
The algorithm is: given the name of a form element
- If the field is set, then we return its value
- Otherwise, we return a default value
We code this algorithm into a function named getValue()
Code for getValue() Function
<?php
// function to get the value of a form field
function getValue($field, $defaultVal = "") {
if (isset($_REQUEST[$field])) {
return $_REQUEST[$field];
}
return $defaultVal;
}
?>
- The function accepts an optional default value in case we want to preset a value in the field
- We code it in the class
FormVerifier class and call it like:
$name = $f->getValue("name");
Superglobal Arrays used with Forms
| Array |
Description |
| $_GET |
Access to variables passed via the HTTP GET method. |
| $_POST |
Access to variables passed via the HTTP POST method. |
| $_REQUEST |
Access to variables passed via both the HTTP GET and POST methods. |
^ top
10.2.5: Verifying Form Data
- To check for errors, we code and use various error-checking functions
- We will need to know which field to check
- We also need to provide an error message if the value fails to validate
- To accomplish this, we will pass two arguments to each verification function
- Name of the field to validate
- Value of the field that caused the error
- Error message if the validation fails
- Anytime a value fails to validate, the function adds the message to an error list
$f->addError($field, $value, $msg)
Possible Functions
- To verify that a form element is not empty:
isEmpty($field, $errorMsg)
To verify that the form variable contains numeric data
isNumeric($field, $errorMsg)
To verify that the form variable contains an integer value
isInteger($field, $errorMsg)
To verify that numeric data falls within a specified range
isWithinRange($field, $errorMsg, $min, $max)
With these functions in mind, coding becomes straightforward
You can see the code by clicking the link:
Later in the course we will look at using regular expressions to verify data
Using the Verification Functions In A Form Page
- To use the functions, we add them to the
checkForm() function of our page
- For example:
function checkForm($f) {
// Code verification tests here
$f->isEmpty('name', "You must enter a name");
$f->isEmpty('state', "You must select a state");
$f->isEmpty('lang', "You must select a language");
return $f->isError();
}
^ top
10.2.6: Error Tracking and Reporting
- Whenever we find an error, we want to add the error to a list
- For each error, we will track its form-field name, value and a message
function addError($field, $value, $msg) {
$this->_errorList[$field] = array(
"field" => $field,
"value" => $value,
"msg" => $msg);
}
Also, we need a function to test if there are any errors
function isError() {
if ($this->_errorList) {
return true;
} else {
return false;
}
}
We may need to reset the error list from time to time
function resetErrorList() {
$this->_errorList = array();
}
In addition, we can code a function to display all the errors
function reportErrors() {
$html = "";
if ($this->isError()) {
$html = "<b>We found some error(s) in the data.</b>
<p>Please resubmit after making these changes:";
$html .= "<ul>";
foreach ($this->_errorList as $err) {
$html .= '<li>'.$err['msg'];
}
$html .= "</ul>";
}
return $html;
}
- To show this error report, we add a call to the function in our form like:
<?php echo $f->reportErrors() ?>
Also, we want some way of highlighting errors on the form
- Makes it easier for users to correct the errors
One way is to add some special highlighting HTML when an error occurs
We can create a function to add this HTML when a form variable is on the error list
function formatOnError($field, $data) {
$html = $data;
if (isset($this->_errorList[$field])) {
$html = "<font color=\"$this->_errColor\">";
$html .= $data.'</font>';
}
return $html;
}
To use this function, we add PHP code to our form like:
<?php echo $f->formatOnError('name', '<i>Name:</i>') ?>
- If there is no error, the code displays: Name:
- Otherwise, the code displays: Name:
You can see all the error handling code by clicking the link:
Another idea, which is not implemented, would be to add a red border around a table cell
^ top
10.2.7: Saving Data and Finishing Up
- After the form data is verified, it is time to save the data
- We use the
saveData() function in our form page
function saveData($f) {
// Save the data;
}
Within the saveData() function we can save the form data to many locations
- Databases
- Cookies
- Files
- Session variables
- URL strings
We know how to save data in the database
- We will discuss other techniques in the future
Example of Saving Data in a Database
function saveData($f) {
// Save the data;
$name = $f->getValue("name");
$sex = $f->getValue("sex");
$state = $f->getValue("state");
include_once("includes/dbconvars.php");
$dbCnx = mysql_connect($dbhost, $dbuser, $dbpwd)
or die(mysql_error());
mysql_select_db($dbname, $dbCnx)
or die(mysql_error());
$sql = "
INSERT INTO someTable(Name, Sex, State)
VALUES ('$name', '$sex', '$state')
";
// For debugging (remove when finished)
var_dump($_REQUEST);
echo "<p>SQL: $sql</p>\n";
die("Stopped for testing"); // stop the redirect
mysql_query($sql) or die(mysql_error());
mysql_close($dbCnx);
}
Finishing Up
- Once the data is saved, you usually want to send the user to another page
- For this you can use the
redirect() function discussed in lesson 9.3.4
function main($title = "") {
if (isset($_POST["submit"])) {
$error = checkForm();
if (!$error) { // data is OK
saveData();
redirect("/index.html?it=worked");
}
}
require("includes/header.php");
showContent($title);
require("includes/footer.php");
}
Note the use of the CGI variable to forward information to the next page
Next week we will look at other techniques to forward data from one page to the next
^ top
10.2.8: Summary
- We created our
FormVerifier class with
- A function to safely get form values
- Error handling and reporting functions
- Data verification functions
- We encapsulated all the necessary variables and functions in the class
- We also organized our form page using functions
- The functions of our page template handle the sequence of form processing
- Controlling the page flow
- Checking data
- Saving data
- Showing the form in a browser
- Following this structure makes form handling faster and easier to develop
Further Information
^ top
Exercise 10.2
In this exercise we explore how to use the FormVerifier class.
Specifications
- Install the following files in a subdirectory of
public_html named includes
- If you cannot see any of the files, then view the source
- Install the following file in
public_html:
- Modify the
formtest.php code to try various error verification functions
- Submit your modified
formtest.php code as part of this weeks exercises.
^ top
10.3: Making Forms More Easily
Objectives
At the end of the lesson the student will be able to:
- Use a class to create and display a form
- Extend a class using inheritance
- Code functions to display form elements
|
^ top
10.3.1: Problems with Repeated Code
- In our formtest.php page, we had repeated code in the
showContent() function
- HTML table tags
<tr> and <td>
- HTML form tags
- PHP code to display previously-entered data
- Repeating code such as this is error prone
- For example, we forget to update one part of a form element
- Then the form works most of the time, but not always
- We spend hours locating and correcting the bug
- Then we find we need to change the form
- But we forget to change one small part...
- There are two techniques to remove repeated code
- First we use loops to reduce the repeated code
- Then we use functions to package the code so we can call it many times
- Once the function is debugged, we can create new forms with fewer errors
Example of Repeated Code in a Form
<tr>
<td><?php echo $f->formatOnError('lang', '<i>Languages:</i>') ?></td>
<td><input type="checkbox" name="lang[]" value="ASP"
<?php
$value = $f->getValue('lang', array('ASP'));
if ($value and is_array($value) and in_array('ASP', $value)) {
echo " checked";
}
?>> ASP
<input type="checkbox" name="lang[]" value="JSP"
<?php
$value = $f->getValue('lang');
if ($value and is_array($value) and in_array('JSP', $value)) {
echo " checked";
}
?>> JSP
<input type="checkbox" name="lang[]" value="PHP"
<?php
$value = $f->getValue('lang');
if ($value and is_array($value) and in_array('PHP', $value)) {
echo " checked";
}
?>> PHP
<input type="checkbox" name="lang[]" value="Other"
<?php
$value = $f->getValue('lang');
if ($value and is_array($value) and in_array('Other', $value)) {
echo " checked";
}
?>> Other
</td>
</tr>
Example of Reducing Repeated Code Using a Loop
<tr>
<td><?php echo $f->formatOnError('lang', '<i>Languages:</i>') ?></td>
<td>
<?php
$values = array("ASP","JSP","PHP","Other");
$selected = array('PHP');
foreach ($values as $item) {
echo "<input type=\"checkbox\" name=\"lang[]\" value=\"$item\"";
$list = $f->getValue('lang', $selected);
if (!is_array($list)) $list = array($list);
if (in_array($item, $list)) {
echo " checked";
}
echo "> $item\n";
}
?></td>
</td>
</tr>
^ top
10.3.2: Extending FormVerifier
- To remove repeated code, we will create several functions to display form elements
makeButton()
makeCheckBoxes()
makeHidden()
makeTextArea()
makeTextInput()
makePassword()
makeRadioGroup()
makeSelect()
- To gain the benefits of OOP, we will encapsulate these functions in a new class:
FormLib
- Many of the functions will need to use the
FormVerifier class
- To enable our functions to work seamlessly with
FormVerifier, we will use inheritance
class FormLib extends FormVerifier
By extending from FormVerifier, we gain access to all the data and functions of FormVerifier
Following is the start of our new class: FormLib
Example Showing the Structure of FormLib
<?php
include_once("formverifier.php");
define("VERTICAL", 1);
define("HORIZONTAL", 2);
class FormLib extends FormVerifier {
//---- private variables ----
var $_formLayout = VERTICAL;
//---- General purpose functions ----
// constructor
function FormLib($layout = VERTICAL, $errColor = "red") {
parent::FormVerifier($errColor);
$this->_formLayout = $layout;
}
//---- Form element functions ----
}
?>
Notes on the Code
- We include
formverifier.php so we can inherit from it
include_once("formverifier.php");
The function define() is used by PHP to define constant values
- Constants help to document the code
Within class FormLib, we declare private variables and a constructor
var $_formLayout = VERTICAL;
After this, we define the constructor for FormLib
The constructor uses the keyword parent to refer to the superclass: FormVerifier
We save the class in a file named formlib.php
^ top
10.3.3: Making Form Elements
- Next step is to write code to display various form elements
- In addition we code functions to make HTML for various form elements
- The easiest functions are
start() and finish
<?php
// Returns HTML to begin a form.
function start($method = 'POST', $action = false, $other = '') {
if (!$action) $action = $_SERVER['PHP_SELF'];
$html = "<form method=\"$method\" action=\"$action\"";
if ($other) $html .= " $other";
$html .= ">\n";
return $html;
}
// Returns HTML to end a form.
function finish() {
return "</form>\n";
}
?>
- Note the
action parameter of the start() function
- If no action is specified, the action is set to the current page
if (!$action) $action = $_SERVER['PHP_SELF'];
Other functions for displaying form elements could include:
makeButton()
makeCheckBoxes()
makeHidden()
makeTextArea()
makeTextInput()
makePassword()
makeRadioGroup()
makeSelect()
The instructor has written several functions that you can use, or you can write your own
- If you find any errors, please report them
One of these functions is shown below along with example code to call the function
You can see all the functions by clicking the link: formlib.php
Example Function to Display HTML Check Boxes
<?php
// Return one or more checkbox HTML form controls.
function makeCheckBoxes($name, $listPairs, $selectList = 0, $other = "") {
$selectList = $this->getValue($name, $selectList);
$html = "";
foreach ($listPairs as $prompt => $value) {
$html .= "<input type=\"checkbox\" name=\"{$name}[]\" value=\"$value\"";
if ($other) $html .= " $other";
if ($selectList AND in_array($value, $selectList)) {
$html .= " checked";
}
$html .= "> $prompt\n";
}
return $html;
}
?>
Example Code to Call the Function makeCheckBoxes()
<?php
$list = array("ASP"=>"ASP", "JSP"=>"JSP",
"PHP"=>"PHP", "Other"=>"Other");
$selectList = array("PHP");
echo $f->makeCheckBoxes('lang', $list, $selectList);
?>
^ top
10.3.4: Example Form Definition
- Let us develop a page to test our
FormLib class
- First we include
formlib.php rather than formverifier.php
include_once("includes/formlib.php");
We modify the main function to instantiate a FormLib object
$f = new FormLib(HORIZONTAL);
Finally, we modify showContents() to make use of the new FormLib functions
Further Abstraction
- We can remove the table tags by using the tablelib.php introduced in lesson 9.4.3
- This is left as an exercise for the student :-)
^ top
10.3.5: Summary
- Using
FormVerifier alone, we noticed repeating code in our forms
- To reduce this repeating code, we developed a set of functions to display form elements
- We developed
FormLib as an extension of FormVerifier using inheritance
- This allowed us to include all the data and functions of
FormVerifier in FormLib
- The complete
FormLib code is available by clicking the link
- To demonstrate the use of
FormLib, we rewrote our example form test code:
^ top
Exercise 10.3
In this exercise we explore how to use the FormLib class to create forms.
Specifications
- Start a text file named exercise10.txt.
- Prepare the exercise header as described in the HowTo on submitting exercises
- Label this exercise: Exercise 10.3
- Install the following files in a subdirectory of
public_html named includes
- Install the following file in
public_html:
- Run the
formtest2.php page and verify it works
- Compare the
showContents() functions in both formtest.php and formtest2.php and write answers to the following questions in your exercise10.txt file.
Q1: Which file has the shorter showContent() function?
Q2: Which showContent() function seems easier for you to use? Why?
- Chose another function from
FormLib and add it to the formtest2.php file.
- Submit your modified
formtest2.php file with the other exercises from this lesson.
^ top
Wrap Up
^ top
Home
| WebCT
| Announcements
| Course info
| Expectations
| Schedule
Project
| Help
| FAQ's
| HowTo's
| Links
Last Updated: December 11 2005 @22:06:04
|