PHP User defined functions

Defining and calling functions

What is a function?

  • function:
    • code to perform a specific task
    • packaged into a single unit
    • can be called upon whenever that task is needed

A function works in three parts:

  • Provide input using arguments
  • Function code processes
  • Receive output as return values

PHP has many built-in functions which can be used. It also allows developers to write their own custom functions.

Let's take a look at an example of a user-defined function.

Example function:

<?php
  function full_name($first_name, $last_name) {
    $result = $first_name . " " . $last_name;
    return $result;
  }

  echo full_name('George', 'Washington');
?>

Defining a function

  • Starts with "function", then space, then function name
  • Followed by comma-delimited arguments in parentheses
    • Can be zero, one, or many arguments
    • Arguments are variables and start with "$"
  • Followed by curly-braces around the function definition
  • Function definition is code for the custom task
  • Then returns a result using "return"

Calling a function

  • Invoke the function name, then values in parentheses
  • Values will be assigned to argument variables
  • Order of the values must match the order of the arguments
  • Each argument must receive a value, unless a default is set

Function naming rules

There are a few rules about which characters are allowed in function names.

  • Uppercase/lowercase letters
  • Numbers
  • Underscores
  • No spaces

When defining or calling functions, function names always require parentheses. This is how PHP recognizes it as a function. This is true even if there are no arguments inside the parentheses.

Example:

<?php
  function scream() {
    return "Yippee!";
  }

  echo scream();
  // Yippee!

  echo scream;
  // Error: Use of undefined constant scream
?>

Function definition rules

PHP only allows defining a function once. Defining it again will raise an error. When using include() or require() to import a file containing functions, it is a good idea to use include_once() or require_once() to make sure the file is not imported a second time.

PHP pre-processes a page of code looking for function definitions. Surprisingly, functions do not need to be defined before calling them. It is possible to call them first and define them later. However, defining functions before calling them is a best practice. It makes code easier to read and maintain.


Function arguments are what give functions their flexibility. After all, functions are meant to be re-usable code which will perform a similar task for different cases. Arguments allow us to provide different input, and different input returns different output.

<?php
  echo full_name('George', 'Washington');
  // George Washington

  echo full_name('John', 'Adams');
  // John Adams
?>

The variables used as arguments are not attached to any variables that are passed in to arguments. It is irrelevant what variable name was used outside the function. The argument will set a new variable for the function to use.

Example:

<?php
  $f = 'Thomas';
  $l = 'Jefferson';
  echo full_name($f, $l);
?>
$f and $l will become $first_name, $last_name inside the function.

A more complex function

This is a real-world example of defining and using a more complex function. We will also refer back to this example in the next sections.

<?php
  function to_sentence($array, $oxford_comma) {
    $last_word = array_pop($array);
    if($array == 0) {
      return $last_word;
    }
    $sentence = implode(', ', $array);
    if($oxford_comma && count($array) > 1) {
      $sentence .= ',';
    }
    $sentence .= " and " . $last_word;
    return $sentence;
  }

  $letters = ['a', 'b', 'c', 'd'];

  echo to_sentence($letters, true);
  // a, b, c, and d

  echo to_sentence($letters, false);
  // a, b, c and d
?>

Note: The "return" in line 4 will return a value and exit the function immediately.


Argument default values

All arguments listed in the function definition will expect values by default. PHP will throw an error if an argument is missing.

<?php
  echo to_sentence($letters, true);
  // a, b, c, and d

  echo to_sentence($letters);
  // Error: missing argument 2

  echo to_sentence($letters, null);
  // a, b, c and d
?>

Notice in the third example that null is considered an acceptable value. The same would be true for 0, "", and false.

Default values can be set for function arguments. Providing a value for the argument becomes optional, and the default value will be used when a value is not provided.

Default values are set by making a variable assignment in the argument list.

<?php
  function to_sentence($array, $oxford_comma=true) {
    // ...
  }

  echo to_sentence($letters);
  // a, b, c, and d
?>

Defaults can be set for multiple arguments.

<?php
  function to_sentence($array=['x','y','z'], $oxford_comma=true) {
    // ...
  }

  echo to_sentence();
  // x, y, and z
?>

Optional arguments at the end

It is important that all optional arguments are at the end of the argument list. That is, to the right of the last argument without a default. This is because PHP needs to maintain the correct order of the values to make correct assignments to the arguments. Leaving out an earlier value would throw off the order.

In this example, $array is not optional. PHP assumes that true must be the value to use for the first argument and that a second argument value was not provided.

<?php
  function to_sentence($array=['x','y','z'], $oxford_comma) {
    // ...
  }

  echo to_sentence(true);
  // Error: Missing argument 2
  // Error: array_pop() expects parameter 1 to be array, boolean given
?>

The second error shows that it is using a boolean value in place of the array.


Function Return Values

Functions should always return a value.

<?php
  function full_name($first_name, $last_name) {
    $result = $first_name . " " . $last_name;
  }

  echo full_name('George', 'Washington');
  // (no output)
?>

There is usually a returned value at the end of the function, but functions can return a value at any point in their code. Any remaining code will not execute.

Look back at the to_sentence() example and notice how line 4 could return a value. If so, the code after line 4 would not execute. If not, then the value in the last line will be returned.


return vs. echo

For output, it is a better practice to return values from a function and then use echo to output the result, instead of using echo to output content from inside the function.

Here is an example where it is difficult to see the difference. Both of these functions have the same result. "9" will be output.

Example using echo:

<?php
  function add($a, $b) {
    echo $a + $b;
  }

  add(2, 7);
  // 9
?>

Example using return:

<?php
  function add($a, $b) {
    return $a + $b;
  }

  echo add(2, 7);
  // 9
?>

Using a return value is more flexible. An echoed value can be output only. But a returned value can be output, assigned to a variable, or used with other code.

Here are two example to demonstrate.

Example using echo:

<?php
  function add($a, $b) {
    echo $a + $b;
  }

  echo "2 + 7 = " . add(2, 7);
  // 92 + 7 = 
?>

Example using return:

<?php
  function add($a, $b) {
    return $a + $b;
  }

  echo "2 + 7 = " . add(2, 7);
  // 2 + 7 = 9
?>

The example using echo does not return the expected result. echo outputs content immediately. The order is: The original line calls the add() function, "9" gets output immediately using echo, then the function returns no value and exits, then the original line outputs "2 + 7 =".

A common technique is to accumulate output in a variable to return at the end. This is done using $sentence in the to_sentence() example. Here is another example.

<?php
  function page_title($text="") {
    $output = "<div id=\"page-title\">";
    $output .= "<h1>";
    $output .= $text;
    $output .= "</h1>";
    $output .= "</div>";
    return $output;
  }
?>

Functions return one value

Functions return only one value. In order to return more than one value use an array.

<?php
  function divide_with_remainder($dividend, $divisor) {
    $quotient = (int)($dividend/$divisor);
    $remainder = $dividend % $divisor;
    return array($quotient, $remainder);
  }

  $result = divide_with_remainder(21, 5);
  echo "21/5 = " . $result[0] . ", remainder " . $result[1];
  // 21/5 = 4, remainder 1
?>

PHP has a built-in variable named list() which can be useful for assigning array values to variables. The variables used as arguments to list() will be assigned array values in the order they appear in the array.

<?php
  list($q, $r) = divide_with_remainder(21, 5);
?>

Notice how much cleaner it is to use list() than it is to assign each element individually.

<?php
  $result = divide_with_remainder(21, 5);
  $q = $result[0];
  $r = $result[1];
?>

Any array elements without corresponding variables in list() will be ignored.

<?php
  list($a, $b) = array(1,2,3,4,5);
  echo $a;
  // 1
  echo $b;
  // 2
?>

Variable Scope

Functions have a self-contained "world" of variables. They keep a division between variables inside and outside the function. The variables used in function have no relationship to outside variables, and vice versa. The "variable scope" is limited to inside the function.

variable scope: the area of code in which variable name has meaning and is "visible"

There are two kinds of scope that variables can have.

global scope: the default area of code (not in a function or class)

local scope: the area of code inside a function or class

Example: scope_test() returns the value passed to $a, not the $a set previously in the global scope.

<?php
  $a = 5;
  function scope_test($a) {
    return $a;
  }
  echo scope_test(8);
  // 8
?>

Functions cannot access variables outside of their local scope.

<?php
  $a = 5;
  function scope_test() {
    return $a;
  }
  echo scope_test();
  // Error: Undefined variable: $a
?>

The global scope cannot access values inside a function.

<?php
  function scope_test() {
    $b = 999;
  }
  scope_test();
  echo $b;
  // Error: Undefined variable: $b
?>

global

The PHP keyword global is used to shared variables between the global and local scopes.

Here it shares a global scope variable with the local scope.

<?php
  $a = 5;
  function scope_test() {
    global $a;
    return $a;
  }
  echo scope_test();
  // 5
?>

Here it shares a local scope variable with the global scope.

<?php
  function scope_test() {
    global $b;
    $b = 999;
  }
  scope_test();
  echo $b;
  // 999
?>

global should be used rarely. It is considered a poor programming practice. It allows a function to alter a global value, and that might happen somewhere deep in the code base, without a developer realizing. It can make bugs hard to track down. It is much better to pass in arguments and return values. Then the data inputs and outputs are easy to see and to test.

Fork me on GitHub