PHP Functions

Chapter 10 21 mins

Learning outcomes:

  1. What is a function
  2. How to create a function
  3. Writing our first function
  4. Function parameters and arguments
  5. The return keyword

Introduction

We've come across quite a few functions uptil this point in this course, including fgets(), strlen(), count(), var_dump() and so on.

An intergral part of programming, functions are in the toolbox of nearly all programming languages in some way or the other. In this chapter, we shall explore functions in PHP at the very basic level.

Let's begin.

What is a function?

Let's start by grasping the idea of a function.

A function represents a block of code that is executed whenever the function is called.

Suppose we want to square a number $a and then subtract from it another number $b, and finally print the result.

To do this for 3 pairs of numbers, we'll simply repeat the block of statements, that accomplishes this for one single pair of numbers, for a total of three times as shown below:

<?php

$a = 10;
$b = 20;
echo $a ** 2 - $b;
echo "\n";

$a = 5;
$b = -2;
echo $a ** 2 - $b;
echo "\n";

$a = 10;
$b = -1;
echo $a ** 2 - $b;
echo "\n";

Imagine we had to do this 1000 times!

Well one way is to copy paste the first block of statements here (from line 3 to line 6) 999 times, changing the values of $a and $b for each new computation. But what if we decide to subtract the square root of $b from twice that of $a, instead of subtracting $b from the square of $a?

You can realise the problem...

We'd need to change the expression in all 1000 occurences!

Even though, in this case, we might be able to get on with finding $a ** 2 and replacing it with $a * 2 and performing other such replacements using a text editor, we won't be so lucky always with our code! In fact, most of the times, this luck isn't there!

So how to solve this problem? How can we group code in one location and then reuse it from that one single location whereby changes are as easy as doing once?

Well the answer is pretty simple — use a function.

A function can be used to define a block of code that can be reused again and again at will.

Plus, since a function can be named (as we shall see below), the purpose of this block of code can be made apparent in the name of the function.

Alright, now it's time to see how to create a function in PHP.

Creating a function

Almost all functional goodness in PHP comes from the function keyword.

Here's the syntax for creating a function:

function function_name(parameters) {
   statement_1;
   statement_2;
   ...
   statement_n;
}

We start with the function keyword followed by the name of the function. The name is an identifier and hence follows the rules for naming identifiers in PHP.

Next comes a pair of parentheses (()) that holds all parameters of the function.

Finally comes the block of statements, enclosed in a pair of braces ({}), that is executed when the function is called. This is referred to as the function's body.

Once a function is created, it can be called - or much better to say, it can be invoked.

Calling a function simply means to execute its body.

A function is called by writing the name of the function followed by a pair of parentheses. For instance, to call the fgets function, we'd write fgets().

Alright, now based on all this information, we'll solve the computation problem mentioned at the start of this chapter, with the help of a function.

Writing your first function

Recall the following code from above:

<?php

$a = 10;
$b = 20;
echo $a ** 2 - $b;
echo "\n";

In this section, we'll create a function to perform this very computation.

First, we ought to settle on a name for the function. Let's call it compute_and_print(), followed by the fact that first we perform a numerical computation and then print it.

After the name, we need to think about its parameter list i.e. what pieces of data would the function need to perform its computation. Well, in this case, we need the values for $a and $b passed into the function and likewise, we'll create two parameters $a and $b.

We'll understand exactly how parameters work later in this chapter.

Moving on, the last thing is to write the body of the function. In our case, the body is merely the last two statements in the code above. The first two statements, where we create the variables $a and $b, aren't included because we need to change this with every new function call.

All together, we arrive at the following function definition:

<?php

function compute_and_print($a, $b) {
   echo $a ** 2 - $b;
   echo "\n";
}

Inside the function, we print $a ** 2 - $b, which is exactly the same expression we were printing in the code above.

Let's now call this function a couple of times:

<?php

function compute_and_print($a, $b) {
   echo $a ** 2 - $b;
   echo "\n";
}

compute_and_print(10, 20);

compute_and_print(5, -2);

Here's what happens in line 8:

  1. The function compute_and_print() is called with the arguments 10 and 20.
  2. Execution shifts to the function in line 3.
  3. The first argument 10 goes into the first parameter $a, while the second argument 20 goes into the second parameter $b.
  4. In the body of the function, the expression $a ** 2 - $b is evaluated and finally its result is printed.

The same process gets repeated for line 10.

Executing this code results in the following:

80 27

Great!

Now suppose that we want to change the expression that performs a computation over the variables $a and $b. With a function, we only ought to make the change once, as compared to before where we needed to change it in every copied occurence of the block of statements.

Consider the code below:

<?php

function compute_and_print($a, $b) {
echo $a ** 2 + $b ** 2; echo "\n"; } compute_and_print(10, 20); compute_and_print(5, -2);
500 29

Nothing is changed except for the line highlighted.

This is the power of functions - or better to say, a glimpse into the power of functions!

Function parameters and arguments

Although we are familiar with the term 'argument' from the PHP Basics chapter, we don't really know yet how to put its essence into our applications.

Let's review what is meant by an argument:

An argument is a datum that we provide to a function so that it can use it to carry out its desired job.

Recall the fgets() function.

When we pass in the STDIN constant as an argument, the function starts reading input from standard input which is typically connected to the terminal. fgets() is meant to start reading input and for that it requires a reference to the underlying stream from where to read data (such as the terminal, or some file).

Arguments are a commonly used feature of functions not just in PHP, but in almost all programming languages.

To get a function to accept a given argument, we first need to set up a parameter on the function.

A parameter is the name with which a given argument can be referred to in the function's body.

A parameter can be thought of as a variable holding a given value. The variable is called the parameter while the exact value it holds is called the argument.

Parameters go inside the pair of parentheses in the function's definition. On the other hand, arguments go inside the pair of parentheses in the function's invocation.

To add a parameter to a function, we first come up with a name for the parameter (which must follow the identifier naming rules in PHP), and then write that inside the pair of parentheses. Multiple parameters can be added by separating them with a , comma.

Let's review the compute_and_print() function we created above:

<?php

function compute_and_print($a, $b) {
   echo $a ** 2 - $b;
   echo "\n";
}

Inside the pair of parentheses (()), notice the parameters $a and $b. They indicate that whenever compute_and_print() is called, it must be called with two arguments — first of which goes in $a and the second of which goes $b.

If we don't pass in exactly two arguments, PHP will signal an error as shown below:

<?php

function compute_and_print($a, $b) {
   echo $a ** 2 - $b;
   echo "\n";
}

// Omitting the second argument.
compute_and_print(10);
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function compute_and_print(), 1 passed in <path> on line 9 and exactly 2 expected in <path>:3 Stack trace: #0 <path>(9): compute_and_print(10) #1 {main} thrown in <path> on line 3

The error message might seem very complex, but if you read it carefully, it's quite simple and self-explanatory:

  1. Firstly, it specifies the type of the error i.e. ArgumentCountError — there is an error in the number of arguments passed in.
  2. Next, it specifies the exact problem in the argument count i.e. Too few arguments, followed by the name of the function i.e. compute_and_print(), followed by the exact argument count currently passed in i.e. 1 in this case.
  3. Even the line where the wrong function call was made is specified i.e. line 9 in addition to the expected count of arguments i.e. exactly 2 expected.
  4. Last but not the least, the exact location where the function is defined is also specified i.e. :3.
For brevity, we've reduced the exact file paths in the error message above to the placeholder <path>.
If we were working with multiple PHP files, then <path> could really help in determining exactly which file has the problem in it.

Apart from this, the stack trace printed is a highly useful feature for debugging functions, and honestly a little bit complicated. We'll cover it in detail in the PHP Functions unit.

Returning values

Functions start to prove even more powerful and capable once we get them to return values.

So what does it mean to return values?

Well, it's very basic. When we call a function, it performs its job and then exits. However, if needed, the function can return its computation's result. This has the effect of replacing the function call with the return value.

This concept is, once again, not a completely new idea — it exists in mathematics as well.

For instance, in the mathematical expression ::f(2) + f(3) + 50::, if we know that the function ::f:: returns the square of the given number, then the expression could be swapped with ::4 + 9 + 50::. The results of ::f(2):: and ::f(3)::, that are ::4:: and ::9:: respectively, replace ::f(2):: and ::f(3):: in the expression.

This exact same idea applies to functions in PHP and almost all high-level structured programming languages.

The main player here is the return keyword.

The return keyword serves to return a value from a function.

The value follows the return keyword.

Let's consider an example to help clarify the idea:

In the code below, we define a function sum() that takes in two numbers as arguments and then returns their sum:

<?php

function sum($a, $b) {
   return $a + $b;
}

Since the function returns the sum, we can use it in other expressions. This is exactly what we do below:

<?php

function sum($a, $b) {
   return $a + $b;
}

echo sum(10, 20), "\n";

echo sum(10, 15) * 20, "\n";

echo 10 + sum(3, 3) - 2, "\n";
30 500 14

In line 7, the call sum(10, 20) is simply replaced with 30.

So is the case with line 9 — sum(10, 15) is replaced with 25, and hence the expression sum(10, 15) * 20 becomes 25 * 20, which then becomes 500.

Try applying this same logic to line 11...

Moving on, one thing to note about return is that, when encountered, it effectively exits the underlying function. That is, any code that comes after the return statement is ignored.

For instance, consider the code below:

<?php

function check_return() {
   echo 'Before return...', "\n";

   return true;

   echo "After return...";
}

check_return();

We have set up a function with an output statement before return and once after it to see which ones are printed.

As expected, when we run this code, the second output isn't made and that's because of return:

Before return...

Execution inside the function ends right at the return statement in line 6.

Often times, as we'll see in later chapters, this behavior is desirable. For instance, a function meant to query a database might return false and skip the logic for constructing and sending a query if there is no connection to the database server.

However, sometimes it can be a typo.

Knowing about this behavior of return is crucially important for any programmer so that he/she can prevent errors arising from the unintended use of return.

Time for a quick test.

What does the code below output?

<?php

function sum($a, $b) {
   return $a + $b;
   echo "Done with the sum.\n";
}

echo sum(10, 20), "\n";
  • 30 Done with the sum.
  • Done with the sum. 30
  • 30
The echo statement inside the function sum() isn't executed because it comes after the return statement. Hence, choice (A) and (B) can't be the right answer. This leaves us with chioce (C).