© Frank M. Kromann 2018
Frank M. KromannBeginning PHP and MySQLhttps://doi.org/10.1007/978-1-4302-6044-8_4

4. Functions

Frank M. Kromann1 
(1)
Aliso Viejo, CA, USA
 

Computer programming exists in order to automate tasks either too difficult or tedious for humans, from mortgage payment calculation to calculating the trajectory of a football launched by a virtual player in a video game You’ll often find that such tasks are comprised of bits of logic that can be reused elsewhere, not only within the same application but also in many other applications. 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 website, when somebody wants to add a product review, or when a visitor signs up for a newsletter. The logic used to validate an e-mail address is surprisingly complex, and therefore it would be ideal to maintain the code in a single location rather than embed it into numerous pages.

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 feature 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. Fortunately, the PHP language comes with more than 1,000 native functions, but it’s also easy to create your own! In this chapter, you’ll learn all about PHP functions, including how to create and invoke them, pass input to them, use type hinting , return both single and multiple values to the caller, and create and include function libraries.

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 the number five to the third power. You can invoke PHP’s pow() function like this:
<?php
    echo pow(5,3);
?>
If you want to store the function output in a variable, you can assign it like this:
<?php
    $value = pow(5,3); // returns 125
    echo $value;
?>
If you want to output the function outcome within a larger string, you need to concatenate it like this:
echo "Five raised to the third power equals ".pow(5,3).".";
Frankly this approach tends to be quite messy, so I suggest first assigning the function output to a variable and then embedding the variable into the string, like so:
$value = pow(5,3);
echo "Five raised to the third power equals {$value}.";
Alternatively, you could use printf(), which was introduced in Chapter 3 :
printf("Five raised to the third power equals %d.", pow(5,3));
In the latter three examples, the following output is returned:
Five raised to the third power equals 125.

Try It

PHP’s library of functions is simply massive, and as a result you’re going to spend quite a bit of time reading the documentation in order to learn more about a particular function’s input parameters and behavior. This is particularly true when you want to use a function such as date(), which supports almost 40 different specifiers for defining how a date should be formatted. Fortunately, the official PHP site offers a convenient shortcut useful for quickly accessing a function by name; just append the function name onto the domain https://www.php.net . Therefore, to access the date() function, navigate to https://www.php.net/date .

After having arrived at the date() manual entry, take a moment to consider how you’d like to format the date. For the purposes of this exercise, let’s use date() to return the date in this format: Thursday, November 2, 2017. Scan the list of format specifiers to find the appropriate combination. The lowercase letter l defines the complete textual representation of the day of the week, capital letter F defines the complete textual representation of the month, lowercase letter n defines the numerical representation of the day of the month, and finally capital letter Y defines the four-digit representation of the year. Therefore, you’ll embed the date() call like into your PHP-enabled page like this:
<?= date('l, F n, Y'); ?>

Admittedly, the date() function is somewhat of an anomaly given the sheer number of format specifiers; most PHP functions accept two or three parameters and that’s it. Even so, chances are you’ll find the ability to quickly navigate to a function to be incredibly handy. Incidentally, it even works for partial function names! For instance, suppose you want to convert a string to all uppercase, but don’t remember the specific function name, only recalling that the name included the string “upper.” Head over to https://www.php.net/upper and you’ll be presented with a list of relevant functions and other documentation entries!

Most modern IDEs like PHP Storm, Sublime Text, Eclipse, etc., provide an autocomplete feature that will show the argument list for any function. This applies to both built-in PHP functions and to functions you write or include from libraries. You don’t have to keep reading the PHP manual every time you want to check the order of arguments, but if you are hunting for functions it’s a handy tool.

Creating a Function

Although PHP’s vast assortment of function libraries is a tremendous benefit to anybody seeking to avoid reinventing the programmatic wheel, eventually you’ll want to encapsulate a task not available 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 your own function. Written in pseudocode, a function definition looks like this:
function functionName(parameters)
{
    function body
}

While PHP does not impose many restrictions on the function name (provided it does not clash with an existing PHP function) nor formatting convention, a commonly used formatting standard is the camel case format ( https://en.wikipedia.org/wiki/CamelCase ), which dictates that the first letter of the function name is lowercase and the first letter of any subsequent compound words are capitalized. Also, you should use descriptive names in order to encourage code readability!

For example, suppose you would like to embed the current date within multiple locations of your site, but would like the convenience of being able to later update the date format at a single location. Create a function called displayDate() , and within it use the date() function in conjunction with the appropriate format specifiers, like so:
function displayDate()
{
    return date('l, F n, Y');
}
The return statement does exactly what the name implies, returning the associated value back to the caller. The caller is the location within the script where the function is called, which might look like this:
<?= displayDate(); ?>

When the function executes, the date will be determined and formatted (e.g., Saturday, August 24, 2016), with the result returned to the caller. Because in this case you’re calling displayDate() in conjunction with PHP’s short echo tag syntax, when the date is returned, it will be embedded directly into the surrounding page.

Incidentally, you’re not required to output the function results. For instance, you could instead assign the results to a variable, like this:
$date = displayDate();

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. The list() construct offers a convenient means for retrieving values from an array, like so:
<?php
    $colors = ["red","blue","green"];
    list($color1, $color2, $color3) = $colors;
?>

Once the list() construct executes, $color1, $color2, and $color3 will be assigned red, blue, and green, respectively. List() looks like a function but it is actually a language construct and used on the left side of the assign operator(=) compared to functions that are used on the right-hand side to calculate and return values that are assigned.

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 Gilmore";
        $user[] = "[email protected]";
        $user[] = "English";
        return $user;
    }
    list($name, $email, $language) = retrieveUserProfile();
    echo "Name: {$name}, email: {$email}, language: {$language}";
?>
Executing this script returns the following:
Name: Jason Gilmore, email: [email protected], language: English

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 calculateSalesTax($price, $tax)
{
    return $price + ($price * $tax);
}

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 data type, 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 calculateSalesTax() function would be called like so:
calculateSalesTax(15.00, .0675);
Of course, you’re not bound to passing static values into the function. You can also pass variables like this:
<?php
    $pricetag = 15.00;
    $salestax = .0675;
    $total = calculateSalesTax($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. In essence the interpreter creates a copy of each variable. If you want these changes to be reflected outside of the function’s scope, you can pass the argument by reference, introduced next.

Note

Unlike languages such as C++, PHP does not require you to define the function before it’s invoked because the entire script is read into the PHP parsing engine before execution. One exception is if the function is defined in an include file, the include/require statement will have to be executed before the function is used.

Default Argument Values

Default values can be assigned to input arguments, which will be automatically assigned to the argument if no other value is provided. To revise the sales tax example, suppose that the majority of your sales take place in Franklin County, Ohio. You could then assign $tax the default value of 6.75 percent, like this:
function calculateSalesTax($price, $tax=.0675)
{
   $total = $price + ($price * $tax);
   echo "Total cost: $total";
}
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. Also, keep in mind you can override $tax, by passing along another taxation rate; 6.75 percent will be used only if calculateSalesTax() is invoked without the second parameter.
$price = 15.47;
calculateSalesTax($price);
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 calculateSalesTax($price, $tax=0)
{
    $total = $price + ($price * $tax);
    echo "Total cost: $total";
}
This allows you to call calculateSalesTax() without the second parameter if there is no sales tax.
calculateSalesTax(42.9999);
It returns the following output:
Total cost: $42.9999
If multiple optional arguments are specified, you can selectively choose which ones are passed along. Consider this example:
function calculate($price, $price2=0, $price3=0)
{
    echo $price + $price2 + $price3;
}
You can then call calculate(), passing along just $price and $price2, like so:
calculate(10, 3);
This returns the following value:
13

Using Type Declarations

Admittedly, I’m putting the cart ahead of the course when it comes to the topic of type hinting, because in this section I’m forced to reference certain terminology and concepts that haven’t yet been formally introduced. However, for sake of completeness, it makes sense to include this section in this particular chapter; therefore, if you find any of this confusing, feel free to bookmark this page and return to this section after having read everything through Chapter 7. PHP 5 introduced a new feature known as type hinting, later renamed to type declarations, which gives you the ability to force parameters to be objects, interfaces, callable, or arrays. The support for scalar (numbers and strings) type hinting was added to PHP 7.0. If the provided parameter is not of the desired type, a fatal error will occur. As an example, suppose you create a class named Customer and want to be certain that any parameter passed to a function named processPayPalPayment() was of type Customer. You could use type hinting to implement this restriction, like so:
function processPayPalPayment(Customer $customer) {
   // Process the customer's payment
}
PHP 7.0 also introduces type hinting for the return values and is done by adding :<type> after the closing parenthesis in the argument list.
function processPayPalPayment(Customer $customer): bool {
   // Process the customer's payment
}

In the example above, a fatal error will be invoked if the function tries to return anything but true or false.

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 instead do something 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 introduced in Listing 4-1. It takes as input four arguments: $paymentNumber, 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.
function amortizationTable($paymentNumber, $periodicPayment, $balance, $monthlyInterest)
{
    static $table = array();
    // 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;
    }
    $table[] = [$paymentNumber,
      number_format($newBalance, 2),
      number_format($periodicPayment, 2),
      number_format($paymentPrincipal, 2),
      number_format($paymentInterest, 2)
    ];
// If balance not yet zero, recursively call amortizationTable()
    if ($newBalance > 0) {
         $paymentNumber++;
         amortizationTable($paymentNumber, $periodicPayment,
                            $newBalance, $monthlyInterest);
    }
    return $table;
}
Listing 4-1

The Payment Calculator Function, amortizationTable()

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

Note that the value returned by the functions return statement is returned to the instance of the function calling it, not to the main script (except for the first call of the function.
<?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);
   $rows =  amortizationTable($paymentNumber, $periodicPayment, $balance, $monthlyInterest);
   // Create table
   echo "<table>";
   echo "<tr>
<th>Payment Number</th><th>Balance</th>
<th>Payment</th><th>Principal</th><th>Interest</th>
</tr>";
    foreach($rows as $row) {
        printf("<tr><td>%d</td>", $row[0]);
        printf("<td>$%s</td>", $row[1]);
        printf("<td>$%s</td>", $row[2]);
        printf("<td>$%s</td>", $row[3]);
        printf("<td>$%s</td></tr>", $row[4]);
    }
   // Close table
   echo "</table>";
?>
Listing 4-2

A Payment Schedule Calculator Using Recursion

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.
../images/314623_5_En_4_Chapter/314623_5_En_4_Fig1_HTML.jpg
Figure 4-1

Sample output from amortize.php

Anonymous Functions

When a function is declared with a name and a parameter list, it can be called from anywhere in the code where it’s defined. In some cases, it makes sense to define a function that is only callable from a specific location. This often used for callback functions where a specific function is called as a result of calling another function. These functions are called anonymous functions or closures. They do not have a function name.

Closures can be defined as content of a variable:
$example = function() {
   echo "Closure";
};
$example();
Note the semicolon after the function definition. When the closure is assigned to a variable, it’s possible to execute the function by using the variable followed by (), as shown in the example. This is similar to defining a named function, assigning a variable the name of the function, and executing the function with the use of the variable as shown here:
function MyEcho() {
   echo "Closure";
};
$example = "MyEcho";
$example();
Closures act as other functions when it comes to scope and access to variables outside of the function. In order to provide access to such variables, PHP provides the keyword use as demonstrated in the following example:
$a = 15;
$example = function() {
  $a += 100;
  echo $a . " ";
};
$example();
echo $a . " ";
$example = function() use ($a) {
  $a += 100;
  echo $a . " ";
};
$example();
echo $a . " ";
$example = function() use (&$a) {
  $a += 100;
  echo $a . " ";
};
$example();
echo $a . " ";

In the first section, the global variable $a is not accessible, causing it to be assigned 0 inside the first closure. In the second section, $a is made available to the closure, but the global value is no affected. In the last section, the global variable $a is made available by reference. This causes the global value to change when the closure is executed.

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 repeatedly 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 library.taxation.php. Do not, however, save this file within the server document root using an extension 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. If you deploy the code on a server where you are in full control over the hard disk and the configuration of the web server, it is recommended that include files are stored outside of the web root. This can be in a folder called include or libraries. If, on the other hand, you are deploying to a shared hosting environment, you might only get access to a single folder, the web root. In that case, it’s important that your library and configuration files use the .php extension. This will ensure they are passed through the PHP interpreter if they are called directly. In that case, they will simply produce an empty document, although any code that is outside of a function will be executed and could return content that will be part of the output.

You can insert this file into scripts using include(), include_once(), require(), or require_once(), each of which was 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 library.taxation.php, you could include it into a script like this:
<?php
    require_once("vendor/autoload.php");
    require_once("library.taxation.php");
    ...
?>

Assuming the vendor folder is outside of the web root, this script will use the configured include_path to look for the directory and file. This is commonly used for libraries installed with Composer. Once included, any of the three functions found in these libraries can be invoked as needed.

Summary

This chapter concentrated on one of the basic building blocks of modern 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 recursive 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 language’s vast swath of array management and manipulation capabilities.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.188.160