PHP contains quite a number of built-in functions, such as isset(), strlen(), and so on. And although built-in functions always accomplish very useful tasks, you can be sure that not every possible function can exist in any version of PHP, even in future versions. So suppose you need a function that doesn't exist in PHP. That's where user-defined functions come into the picture—essentially you have the capability to author your own functions, and make them do whatever you want!
Any functions that you create are called user-defined functions. You use the function keyword to define a function and, once defined, that function may be used anyplace in your code, simply by calling its name. When combined with the capability to include files, functions become a very powerful tool in your programming arsenal.
Functions enable you to encapsulate sections of code as though they were independent stand-alone programs. You can pass values into them, and get values out of them. You can call functions at any time during your PHP script, and redirect the flow of execution in this way.
Functions also introduce the idea of scope (fully discussed later in this chapter) into your programs. The normal process in your PHP programs is that once a variable is created, the name you have assigned to it, and the value, persist until you alter it or until the script ends. However, in functions you have to learn to deal with the idea that variables might only exist inside a function, whereas outside it they have no value.
In this chapter you'll build some functions that will work on the same principle as the readymade ones you've already used: when you supply them with information, they will perform an operation and return an answer.
The Structure of Functions
Functions are sections of code that are defined by the user to perform a specific task, and given a name by which to call them. You already know that functions can take values called arguments as input, perform some operations, and then may return another value. The function transfers any argument values into new variables called parameters, which can then be used within the function. You've used PHP's built-in functions extensively in this book so far; to do things like get the data type of a variable (gettype()) right through to sorting arrays (sort()). Writing your own function means you get to give it your own made-up name, but you call it the same way as calling the built-in functions.
Take a look at how functions work, step-by-step:
- The function is written with a name followed by parentheses. Inside the parentheses are the names of any values the function accepts (these values, called arguments, are optional), written as variable names (preceded by a dollar sign like any normal variable) and separated by commas.
- The function is called by writing its name and parentheses. If the function requires any arguments, they are included within the parentheses and are separated by commas. Arguments may be variables or hard-coded values, and do not have to be the same as the variable names in the argument list in the defined function.
- When the function is called, arguments passed to it are turned into parameters, and the parameters are used inside the function to perform the data processing specified by the function. Think of parameters as placeholders for values being passed into the function.
- The return keyword may be used to pass values back out to the calling code after data processing is complete inside the function. Returning values is optional; some functions just do their work and then end without any further notification required. However, it is a good idea to at least return a true or false value to indicate to the rest of your code whether the function successfully completed its work.
- If a value is passed back out of the function, it can be expressed using the echo statement, or it can be assigned to a variable outside the function.
Defining and Calling Functions
You begin creating a function by writing the function keyword followed by a space and then the name you want the function to be addressed by. If you want your function to accept arguments (it doesn't have to), list them in parentheses after the name of the function. Then the code that runs when the function is called is placed within curly braces, the same way you delimit blocks of code in conditional structures. Here's the syntax:
function functionname (parameters)
{
//put your function code here
}
For example, if you want to write a function that calculates a bonus, code such as this would do:
function bonus($sales)
{
$bonus = $sales * 0.15;
return $bonus;
}
Notice the return statement in this example. If your function simply records something in a database, there may not be any return value. If you want the function to send data back out, you must use the return statement, in the manner shown. For example, this is what it would look like if you had some code calling your newly defined function:
$my_total_sales = 120499;
//find out my bonus, based on my total sales
$my_bonus = bonus($my_total_sales);
Because the example returns the result of the calculation on the incoming value (in this case, $120,499), as set in the variable $my_total_sales), the variable $my_bonus will end up being set equal to the outgoing value returned by the function.
You can put as many lines of code as you want in a function, and a line of code can do anything within the bounds of what PHP can ordinarily do: connect to a database, open a file, match a regexp pattern, and so on. You can also make the function echo text out, or print something to the screen.
The return statement, by itself, doesn't display a value; it just passes the result (if any) to the function. The process of executing the contents of a function within a PHP script is known as calling the function.
You can supply a function directly with a number:
echo (bonus(120499));
or you can furnish the function with the name of an already created variable:
$total_sales=120499;
echo (bonus($total_sales));
You can supply more than one parameter to the function, but you must separate each parameter with a comma as illustrated here:
function bonus($total_sales, $bonus_factor) { $bonus = $total_sales * $bonus_factor; return $bonus; }
To call the modified bonus function, you'd supply two values: total_sales and bonus_factor, like this:
$total_sales = 120000;
$bonus_factor = 0.15;
echo (bonus($total_sales, $bonus_factor));
Functions can be defined anywhere within your PHP program. It's common to define functions in a separate file and simply include (or require) that file at the beginning of the main processing file you're creating. You don't need to define or initialize your variables before you define your function; you do, however, need to make sure they are defined or initialized before you call the function.
For example, the following code works:
<?php
$total_sales = 190999; // Execution will start here
$bonus_factor = 0.15;
echo (bonus($total_sales, $bonus_factor)}; // Function called here
function bonus($total_sales, $bonus_factor) // Function defined here
{
$bonus = $total_sales * $bonus_factor;
return $bonus;
)
?>
But the following also works just fine:
<?php
function bonus($total_sales, $bonus_factor) // Function defined here
{
$bonus = $total_sales * $bonus_factor;
return $bonus;
}
$total_sales = 190999; // Execution will start here
$bonus_factor = 0.15;
echo (bonus($total_sales, $bonus_factor)); // Function called here
?>
And here's an important note about the way functions work. You can use any variable names outside the function to pass values inside the function. For example, suppose instead of using exactly the same names ($total_sales and $bonus_factor) both outside and inside the bonus function, you used $out_total_sales and $out_bonus_factor for the variables that exist outside the function, and $in_total_sales and $in_bonus_factor for the variable inside the function. It would work just fine, and would simply look like this:
<?php function bonus($in_total_sales, $in_bonus_factor) // Function defined here { $bonus = $in_total_sales * $in_bonus_factor; return $bonus; } $out_total_sales = 190999; // Execution will start here $out_bonus_factor = 0.15; echo (bonus($out_total_sales, $out_bonus_factor)); // Function called here ?>
Now take another look at parameters and how they work. When you write a function and define it with one or more variables within the parentheses following the function name, the variables are said to be arguments. When you actually call a function and send data into it (as arguments to the function), the values in the arguments (whether they come in as variables or as hard-coded values) are turned into parameters. Parameters are like temporary variables inside a function, and whereas they are being processed within the function (and perhaps take on new values during processing) they remain parameters.
After the resulting values of processed parameters are passed back out of the function, the parameters vanish. What parameters do (appear when the function is called and then disappear when the function completes processing) is completely unrelated to any variables you might create inside the function.
Before you write another user-defined function as a working example, here's a recap:
- User-defined functions are named by the developer.
- Functions may take parameters, which are values or variables defined in parentheses after the function name.
- Multiple parameters are separated by commas.
- The code of the function body is provided in braces after the function name and parameters.
- You must use the return keyword inside the function to return a value that you can use outside the function.
- If there is no value to return, the return keyword just denotes the end of the function code.
- Functions aren't actually executed until called from a line of code within your PHP script.
- You may call a function either before or after it appears in the code—it doesn't matter where you put a function in your code.
- You can call a function as few or as many times as you need, and you can send any values you like into the function, sending them as hard-coded values or as values inside their own variables.
That last item in the recap list should clue you in about code reuse; not having to rewrite the lines of code processed by a function every time you need those lines of code to run is a major savings in coding and debugging effort.
Now take the holiday.php example code from earlier chapters and write a function to calculate the expenses for the holiday break week. You'll see that you end up saving quite a few lines of code.
Try it Out: Using a Simple Function
- Enter the following code and save it as holiday3.php (you can use sections of your previously written code to save time if you like):
<html> <head><title></title></head> <body> <b>Namllu Holiday Booking Form</b> <?php function calculator($price, $city_modifier, $star_modifier) { return $price = $price * $city_modifier * $star_modifier; } if (isset($_POST['posted'])) { $price = 500; $star_modifier = 1; $city_modifier = 1; $destgrade = $_POST['destination'].$_POST['grade']; switch($destgrade) { case "Barcelonathree"; $city_modifier = 2; break; case "Barcelonafour"; $city_modifier = 2; $star_modifier = 2; break; case "Viennathree"; $city_modifier = 3.5; break; case "Viennafour"; $city_modifier = 3.5; $star_modifier = 2; break; case "Praguethree"; break; case "Ppraguefour"; $star_modifier = 2; break; default; $city_modifier = 0; echo ("Please go back and try it again"); break; } if ($city_modifier <> 0) { echo "The cost for a week in $_POST[destination] is " . "$" . calculator($price, $city_modifier, $star_modifier); } } ?> <form method="POST" action="holiday3.php"> <input type="hidden" name="posted" value="true"> Where do you want to go on holiday? <br> <br> <input name="destination" type="radio" value="Prague"> Prague <br> <input name="destination" type="radio" value="Barcelona"> Barcelona <br> <input name=="destination" type="radio" value="Vienna"> Vienna <br> <br> What grade of hotel do you want to stay at? <br> <br> <input name="grade" type="radio" value=" three "> Three star <br> <input name="grade" type="radio" value="four"> Four star <br> <br> <input type="submit" calue=" Check Prices"> </form> </body> </html>
- Save and close the file
- Open holiday3.php in your browser, enter some choices, and submit the form. The holiday3.php example should work just fine:
How it Works
The holiday form should be very familiar by now, it's simply capturing two variables from the user via the $_POST variable ($_POST[destination] and $_POST[grade]) and passing them along to the PHP script. The PHP code starts with the function (named calculator) to calculate the cost of our holiday:
function calculator($price, $city_modifier, $star_modifier)
{
return $price = $price * $city_modifier * $star_modifier;
}
The user-defined calculator() function takes three parameters: the basic price of the holiday, the adjustment to the price for the chosen city, and the final adjustment for the star rating of the hotel. It multiplies these three variables together and returns one value ($price), the total price of the hotel.
The rest of the program works the same as before, concatenating destination and grade into a single value that is used to switch through the various options. There is one small change within the default option, though: the content of the $city_modifier variable is changed to zero if none of the cases are executed. Before executing the calculator() function, you check to see whether the $city_modifier variable has been set to 0; if it hasn't, you can call the function within the echo() statement, using the concatenate operator (the period) to add text to your function result:
if ($city_modifier <> 0) { echo "The cost for a week in $_POST[destination] is " . "$" . calculator($price, $city_modifier, $star_modifier); }
Switching Functions
In the same way that you can use the switch structure to switch among various processing options within a PHP program, you can write your own functions that accept incoming values and, based on those values, switch among various other functions for processing. This is a very powerful feature of user-defined functions in PHP.
Here's a quick example. Suppose you want to create an application that pulls records from various tables in a database. You might send an input value in a variable called $ table_name to the switching function, and within that function decide which query function to run, as shown in this code:
function query switch($table_name) { switch ($table_name) { case "clients": $query = query__clients_gen()); break; case "orders": $query = query_orders_gen()); break; case "employees": $query = query_employees_gen()) ; break; default: echo "Please select a table name"; } } function query_client_gen() { //composes a database query to select records from the clients table } function query_orders_gen() { //composes a database query to select records from the orders table } function query_employees_gen() { //composes a database query to select records from the employees table }
The beauty of using this type of structure is that you can place the functions you've written into an include file, and then include the functions in any page, making it easy to add the composition of database queries to any page you like. In addition, you only need to change the code once if you're making an improvement to it, and the code is easier to read through. In fact, once you're confident that the functions do what you intend, you don't really have to read through them as you're coding, you can just call them whenever you need them.
Because you can assign the result of a function (one that has a return value) directly to a variable, you can simply use the result of a function in a switch..case statement. For example, suppose you create a small management function that tells you how many hits occurred on a page. You can take the number of hits returned by the function and use it to echo out an easy-to-understand message to the user, as this code shows:
switch ($hit_counter = get_hits ($current_page)) { case $hit_counter <100: echo "Few hits today"; break; case $hit_counter <1000: echo "Lots of hits today"; break; case $hit_counter <:10000: echo "Too many hits today"; break; }
The variable $hit_counter would then be able to store whatever the function get_hits($current_page) returned (where $current_page is set to the filename of the current page, and gets the total number of hits today from your hit tracking program). You can place and set the value of the $hit_counter variable right inside the brackets of the switch() statement.
As a utility, you could set this function within each page and have it run once each time the page is displayed. The user would immediately see an indication of the number of hits for that page (although some users might be tempted to keep refreshing the page to up the number of hits).
How Values Get Inside Functions
As discussed earlier, parameters are placeholders representing values passed into a function. But there is more than one way to get a value into a parameter so that the function can work on it. You can pass a value into a function by value or by reference. The difference is subtle, but sometimes very important.
When you pass a value into a function by value, you assign the value directly to a parameter. But when you pass a value into a function by reference, you connect the parameter directly to a variable outside the function, forcing the outside variable to adopt whatever value the parameter gets.
Passing Values by Value
All the functions you've seen so far passed values by value. A value is passed into the function by entering the value (literally, or by naming the variable containing the value) into the spot reserved for that value (the place within the parentheses following the function call).
For instance, in the first bonus example, you can pass in the total sales value by entering a number directly into the spot reserved for the argument, or you can simply set a variable equal to total sales and then enter the variable name into that spot. The following code shows both methods of passing by value:
function bonus($total_sales) { $bonus = $total_sales * 0.15; return $bonus; } $total_sales = 120499; echo "Your bonus is " . bonus($total_sales); echo "Your total sales were " . $total_sales; echo "Your total sales were $120,499 and your bonus is " . bonus(120499);
Notice that even after the value of $total_sales is set outside the function and then passed inside the function for processing, the external value of $total_sales is not changed. No surprises here.
Passing Values by Reference
Passing values into a function by reference has a completely different effect. The external variable used to contain the value being passed into the function is actually changed while the value is being processed. It changes because, in fact, you're not passing a value into the function, you're passing a reference that points directly to the external function. It's as though all processing operations taking place inside the function are actually affecting the external variable directly.
How is it done? Put the ampersand (&) before the name of the argument to be passed by reference. Our next example shows this for the $salary argument.
So suppose you were adding a bonus to a variable called $salary. Obviously you could do that outside the function, but perhaps it would be a little easier and cleaner to do it inside the function. The following code shows how this could work:
function bonus($total_sales,&$salary) { $bonus = $total_sales * 0.15; $salary = $salary + $bonus; return $salary; } $total_sales = 120499; $salary = 40000; bonus ($total_sales, $salary); echo "Your salary, including your bonus is " . $salary; echo "Your total sales were " . $total_sales;
In this case, you don't need to set any variable to the value resulting from calling the bonus() function; you set $ salary to 40,000, then pass it by reference into the bonus() function, and when the function is done, it passes the value directly back into the $salary variable by reference. Neat, eh!
Setting Default Parameter Values
Like many other programming and computer related things, you can write your functions to have default values. For example, you can define an argument as having a default value, which the parameter for that argument will adopt when the function is called, provided you don't pass a value in for that argument.
But there is one catch: you must define any arguments with default values to the right of any arguments without default values. This is a little odd, but if you don't write your functions that way, they won't work as you'd expect. The following example writes the bonus function with a default value of $40,000 for salary to the right of the argument for total_sales:
function bonus($total_sales, &$salary = 40000) { $bonus = $total_sales * 0.15; $salary = $salary + $bonus; return $salary; } $total_sales = 120499; bonus($total_sales); echo "Your salary, including your bonus is " . $salary; echo "Your total sales were " . $total_sales;
This means that if you supplied no $salary value to the function, it would automatically use 40000 to calculate with. But if you do pass a value (higher, lower, the same—it doesn't matter) to the function for salary, the function would use the passed value to calculate with.
Parameter Order Matters
When you call a PHP function, whether you wrote it or it's built-in, the order in which you pass argument values does matter. If you leave an argument(s) out at the end of the list of arguments, you can leave off the last comma separating arguments. Also, if you leave out an argument, the function will automatically assume a zero value for a numerical argument, or an empty string for a string argument (unless the function defines a default parameter value itself), and continue processing. You'll only get a warning or error message when a required argument (one without any default value set) is missing, but of course, the level of warning or error message you receive will depend on the version of PHP you're using and also possibly on the way you're set error reporting.
