Tuesday, July 14, 2009

Beginning PHP and Oracle From Novice to Professional by W. Jason Gilmore and Bob Bryla Chapter 4

Computer programming exists in order to automate tasks of all sorts, from mortgage payment calculation to determining a person’s daily recommended caloric intake. However, as these tasks
grow increasingly complex, you’ll often find they comprise other often repetitive tasks. For example, an e-commerce application might need to validate an e-mail address on several different pages, such as when a new user registers to use a Web site, when somebody wants to add a product review, or when a visitor signs up for a newsletter. The regular expression used to validate an e-mail address is quite complex, and therefore it would be ideal to maintain it in a single location rather than embed it into numerous pages, particularly if it needs to be modified to account for a new domain (such as .museum).
Thankfully, the concept of embodying these repetitive processes within a named section of code and then invoking this name when necessary has long been a key component of modern computer languages. Such a section of code is known as a function, and it grants you the convenience of a singular point of reference if the process it defines requires changes in the future, which greatly reduces both the possibility of programming errors and maintenance overhead. In this chapter, you’ll learn all about PHP functions, including how to create and invoke them, pass input to them, return both single and multiple values to the caller, and create and include function libraries. Addi- tionally, you’ll learn about both recursive and variable functions.

Invoking a Function

More than 1,000 functions are built into the standard PHP distribution, many of which you’ll see throughout this book. You can invoke the function you want simply by specifying the function name, assuming that the function has been made available either through the library’s compilation into the installed distribution or via the include() or require() statement. For example, suppose you want to raise five to the third power. You could invoke PHP’s pow() function like this:
<?php
$value = pow(5,3); // returns 125 echo $value;

?>

this:

If you want to output the function results, you can bypass assigning the value to a variable, like

<?php
echo pow(5,3);
?>

81

If you want to output function outcome within a larger string, you need to concatenate it like this:

echo "Five raised to the third power equals ".pow(5,3).".";

Or perhaps more eloquently, you could use printf():

printf("Five raised to the third power equals %d.", pow(5,3));

In either case, the following output is returned:

Five raised to the third power equals 125.

■Tip You can browse PHP’s massive function list by visiting the official PHP site at http://www.php.net/ and
perusing the documentation. There you’ll find not only definitions and examples for each function broken down by library, but reader comments pertinent to their usage. If you know the function name beforehand, you can go directly to the function’s page by appending the function name onto the end of the URL. For example, if you want to learn more about the pow() function, go to http://www.php.net/pow.

Creating a Function

Although PHP’s vast assortment of function libraries is a tremendous benefit to anybody seeking to avoid reinventing the programmatic wheel, sooner or later you’ll need to go beyond what is offered in the standard distribution, which means you’ll need to create custom functions or even entire function libraries. To do so, you’ll need to define a function using a predefined template, like so:

function functionName(parameters)
{
function-body
}

For example, consider the following function, generateFooter(), which outputs a page footer:

function generateFooter()
{
echo "Copyright 2007 W. Jason Gilmore";
}

Once defined, you can call this function like so:

<?php generateFooter();
?>

This yields the following result:

Copyright 2007 W. Jason Gilmore

Passing Arguments by Value

You’ll often find it useful to pass data into a function. As an example, let’s create a function that calculates an item’s total cost by determining its sales tax and then adding that amount to the price:

function calcSalesTax($price, $tax)
{
$total = $price + ($price * $tax);
echo "Total cost: $total";
}

This function accepts two parameters, aptly named $price and $tax, which are used in the
calculation. Although these parameters are intended to be floating points, because of PHP’s weak typing, nothing prevents you from passing in variables of any datatype, but the outcome might not be what you expect. In addition, you’re allowed to define as few or as many parameters as you deem necessary; there are no language-imposed constraints in this regard.
Once defined, you can then invoke the function as demonstrated in the previous section. For example, the calcSalesTax() function would be called like so:

calcSalesTax(15.00, .075);

Of course, you’re not bound to passing static values into the function. You can also pass vari- ables like this:

<?php
$pricetag = 15.00;
$salestax = .075;
calcSalesTax($pricetag, $salestax);
?>

When you pass an argument in this manner, it’s called passing by value. This means that any
changes made to those values within the scope of the function are ignored outside of the function. If you want these changes to be reflected outside of the function’s scope, you can pass the argument by reference, introduced next.

■Note You don’t necessarily need to define the function before it’s invoked because PHP reads the entire script
into the engine before execution. Therefore, you could actually call calcSalesTax() before it is defined, although such haphazard practice is not recommended.

Passing Arguments by Reference

On occasion, you may want any changes made to an argument within a function to be reflected outside of the function’s scope. Passing the argument by reference accomplishes this. Passing an argument by reference is done by appending an ampersand to the front of the argument. An example follows:
<?php

$cost = 20.99;
$tax = 0.0575;

function calculateCost(&$cost, $tax)
{
// Modify the $cost variable
$cost = $cost + ($cost * $tax);

// Perform some random change to the $tax variable.
$tax += 4;
}
calculateCost($cost, $tax);
printf("Tax is %01.2f%% <br />", $tax*100);
printf("Cost is: $%01.2f", $cost);

?>

Here’s the result:

Tax is 5.75% Cost is $22.20

Note the value of $tax remains the same, although $cost has changed.

Default Argument Values

Default values can be assigned to input arguments, which will be automatically assigned to the argu- ment if no other value is provided. To revise the sales tax example, suppose that the majority of your sales are to take place in Franklin County, Ohio. You could then assign $tax the default value of 6.75 percent, like this:

function calcSalesTax($price, $tax=.0675)
{
$total = $price + ($price * $tax);
echo "Total cost: $total";
}

You can still pass $tax another taxation rate; 6.75 percent will be used only if calcSalesTax() is
invoked, like this:

$price = 15.47;
calcSalesTax($price);

Default argument values must appear at the end of the parameter list and must be constant expressions; you cannot assign nonconstant values such as function calls or variables.
You can designate certain arguments as optional by placing them at the end of the list and assigning them a default value of nothing, like so:

function calcSalesTax($price, $tax="")
{
$total = $price + ($price * $tax);
echo "Total cost: $total";
}

This allows you to call calcSalesTax() without the second parameter if there is no sales tax:

calcSalesTax(42.00);

This returns the following output:

Total cost: $42.00

If multiple optional arguments are specified, you can selectively choose which ones are passed along. Consider this example:

function calculate($price, $price2="", $price3="")
{
echo $price + $price2 + $price3;
}

You can then call calculate(), passing along just $price and $price3, like so:

calculate(10, "", 3);

This returns the following value:

13

Returning Values from a Function

Often, simply relying on a function to do something is insufficient; a script’s outcome might depend on a function’s outcome, or on changes in data resulting from its execution. Yet variable scoping prevents information from easily being passed from a function body back to its caller; so how can we accomplish this? You can pass data back to the caller by way of the return() statement.

The return Statement

The return() statement returns any ensuing value back to the function caller, returning program control back to the caller’s scope in the process. If return() is called from within the global scope, the script execution is terminated. Revising the calcSalestax() function again, suppose you don’t want to immediately echo the sales total back to the user upon calculation, but rather want to return the value to the calling block:

function calcSalesTax($price, $tax=.0675)
{
$total = $price + ($price * $tax);
return $total;
}

Alternatively, you could return the calculation directly without even assigning it to $total, like this:

function calcSalesTax($price, $tax=.0675)
{
return $price + ($price * $tax);
}

Here’s an example of how you would call this function:

<?php
$price = 6.99;
$total = calcSalesTax($price);
?>

Returning Multiple Values

It’s often convenient to return multiple values from a function. For example, suppose that you’d like to create a function that retrieves user data from a database, say the user’s name, e-mail address,

and phone number, and returns it to the caller. Accomplishing this is much easier than you might think, with the help of a very useful language construct, list(). The list() construct offers a conve- nient means for retrieving values from an array, like so:
<?php
$colors = array("red","blue","green");
list($red, $blue, $green) = $colors;
?>

Once the list() construct executes, $red, $blue, and $green will be assigned red, blue, and
green, respectively.
Building on the concept demonstrated in the previous example, you can imagine how the three prerequisite values might be returned from a function using list():
<?php
function retrieveUserProfile()
{
$user[] = "Jason";
$user[] = "jason@example.com";
$user[] = "English";
return $user;
}

list($name, $email, $language) = retrieveUserProfile();
echo "Name: $name, email: $email, language: $language";
?>

Executing this script returns the following:

Name: Jason, email: jason@example.com, language: English

This feature is quite useful and will be used repeatedly throughout this book.

Recursive Functions

Recursive functions, or functions that call themselves, offer considerable practical value to the programmer and are used to divide an otherwise complex problem into a simple case, reiterating that case until the problem is resolved.
Practically every introductory recursion example involves factorial computation. Let’s do some- thing a tad more practical and create a loan payment calculator. Specifically, the following example uses recursion to create a payment schedule, telling you the principal and interest amounts required of each payment installment to repay the loan. The recursive function, amortizationTable(), is intro- duced in Listing 4-1. It takes as input four arguments: $pNum, which identifies the payment number;
$periodicPayment, which carries the total monthly payment; $balance, which indicates the remaining loan balance; and $monthlyInterest, which determines the monthly interest percentage rate. These items are designated or determined in the script listed in Listing 4-2.

Listing 4-1. The Payment Calculator Function, amortizationTable()

function amortizationTable($pNum, $periodicPayment, $balance, $monthlyInterest)
{
// Calculate payment interest
$paymentInterest = round($balance * $monthlyInterest, 2);

// Calculate payment principal
$paymentPrincipal = round($periodicPayment - $paymentInterest, 2);

// Deduct principal from remaining balance
$newBalance = round($balance - $paymentPrincipal, 2);

// If new balance < monthly payment, set to zero if ($newBalance < $paymentPrincipal) {
$newBalance = 0;
}

printf("<tr><td>%d</td>", $pNum); printf("<td>$%s</td>", number_format($newBalance, 2)); printf("<td>$%s</td>", number_format($periodicPayment, 2)); printf("<td>$%s</td>", number_format($paymentPrincipal, 2)); printf("<td>$%s</td></tr>", number_format($paymentInterest, 2));

# If balance not yet zero, recursively call amortizationTable()
if ($newBalance > 0) {
$pNum++;
amortizationTable($pNum, $periodicPayment,
$newBalance, $monthlyInterest);
} else {
return 0;
}

}

After setting pertinent variables and performing a few preliminary calculations, Listing 4-2
invokes the amortizationTable() function. Because this function calls itself recursively, all amorti- zation table calculations will be performed internal to this function; once complete, control is returned to the caller.

Listing 4-2. A Payment Schedule Calculator Using Recursion

<?php
// Loan balance
$balance = 10000.00;

// Loan interest rate
$interestRate = .0575;

// Monthly interest rate
$monthlyInterest = $interestRate / 12;

// Term length of the loan, in years.
$termLength = 5;

// Number of payments per year.
$paymentsPerYear = 12;

// Payment iteration
$paymentNumber = 1;

// Determine total number payments
$totalPayments = $termLength * $paymentsPerYear;

// Determine interest component of periodic payment
$intCalc = 1 + $interestRate / $paymentsPerYear;

// Determine periodic payment
$periodicPayment = $balance * pow($intCalc,$totalPayments) * ($intCalc - 1) / (pow($intCalc,$totalPayments) - 1);

// Round periodic payment to two decimals
$periodicPayment = round($periodicPayment,2);

// Create table
echo "<table width='50%' align='center' border='1'>";
echo "<tr>
<th>Payment Number</th><th>Balance</th>
<th>Payment</th><th>Interest</th><th>Principal</th>
</tr>";

// Call recursive function
amortizationTable($paymentNumber, $periodicPayment, $balance,
$monthlyInterest);

// Close table echo "</table>";
?>

Figure 4-1 shows sample output, based on monthly payments made on a five-year fixed loan of
$10,000.00 at 5.75 percent interest. For reasons of space conservation, just the first 12 payment iterations are listed.

Figure 4-1. Sample output from amortize.php

Function Libraries

Great programmers are lazy, and lazy programmers think in terms of reusability. Functions offer a great way to reuse code and are often collectively assembled into libraries and subsequently repeat- edly reused within similar applications. PHP libraries are created via the simple aggregation of function definitions in a single file, like this:

<?php
function localTax($grossIncome, $taxRate) {
// function body here
}
function stateTax($grossIncome, $taxRate, $age) {
// function body here
}
function medicare($grossIncome, $medicareRate) {
// function body here
}
?>

Save this library, preferably using a naming convention that will clearly denote its purpose, such
as taxes.library.php. Do not however save this file within the server document root using an exten- sion that would cause the Web server to pass the file contents unparsed. Doing so opens up the possibility for a user to call the file from the browser and review the code, which could contain sensitive data. You can insert this file into scripts using include(), include_once(), require(), or require_once(), each of which is introduced in Chapter 3. (Alternatively, you could use PHP’s auto_prepend configuration directive to automate the task of file insertion for you.) For example, assuming that you titled this library taxation.library.php, you could include it into a script like this:

<?php require_once("taxation.library.php");
...
?>

Once included, any of the three functions found in this library can be invoked as needed.

Summary

This chapter concentrated on one of the basic building blocks of modern-day programming languages: reusability through functional programming. You learned how to create and invoke functions, pass information to and from the function block, nest functions, and create both recursive and variable functions. Finally, you learned how to aggregate functions together as libraries and include them into the script as needed.
The next chapter introduces PHP’s array features, covering the languages’s vast swath of array
management and manipulation capabilities.

0 comments: