PDA

View Full Version : Hall of Famer's PHP Tutorials: Chapter 5 - PHP Function Basics


Hall of Famer
11-23-2012, 01:05 AM
Chapter V - Function Basics


In chapter 4, you learned how to play with PHP's iteration/loop structure. These are the very basic contents of PHP as a programming language, and guess what? You are just one step away from turning yourself from a noncoder into a beginner programmer! To complete this step, you need the knowledge of functions.

You may wonder why functions are useful, the idea is to be able to group common functionalities and reuse code. The worst practice of programming is needless repetition, keep this in mind.

This tutorial will teach you how to declare functions, create functions with arguments, functions with return values/void, variable scope in functions and return function value by reference. Since there are just too many concepts involved with functions, I've decided to write two separate articles about the basics and advanced materials. The other one will be posted after the introduction of PHP arrays, strings, superglobals and mysql, before we move onto the world of object oriented programming. Note you need to understand the basics of functions in order to learn concepts like arrays, strings and so on.

1. Declare a function:
To declare a function, you use the function keyword followed by the function name and parenthesis (). It sounds simple, isnt it? Now lets give this a try:


function myfunc();
A function like this is pretty simple and is practically rare. To proceed further, think about what a math function y = f(x) does? Yes, it receives a value x, applies some operations behind the scene, and the return a value y! A math function without a supplied value x does nothing for you.

Supplied values are called arguments in programming languages such as PHP. Sure a PHP function can survive just fine without an argument, but in most circumstances functions do accept arguments and perform on them. So lettuce modify the function a bit so it can accept external variables as arguments:


function myfunc($x, $y);
Alright, the function looks better than before. Here's a small tip, sometimes you may want to supply a default value for function arguments. You will see the usefulness of this soon in the next few sections. The sample code is given below:


function myfunc($x, $y = 0);
2. Create the function body:
Our tiny little function isnt quite useful at this point, this is because we have not define any functionalities inside the function itself. To accomplish this, we need to write code in the function body. PHP can distinguish what are inside and outside of the function if you enclose lines belong to a function within curly bracket{}. An example is given below:


// code outside of function
function myfunc($x, $y = 0){
// code inside the function
}
// code outside of function
With this in mind, we can start to write some lines for our beloved function. Lettuce begin baking some codes!


function myfunc($x, $y = 0){
// compute ax2 + bxy + cy2
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2);
}
Now our function actually does something, it computes a second order formula with two variables x and y. The variables a, b and c are defined inside the function, they are local variables only accessible inside the function itself!

Such a function above is called a void function, which performs operations but does not return any values. Void functions are useful in mysql insert, update and delete operations, since all you care about is the operation succeeds. Imagine, however, you are playing with mysql select operations in order to retrieve some database record. In this case, a function that does not return anything is clearly not what you want. You can have a function to return a single value by using the keyword return, this will stop function execution immediately and returns the value you want back to the main program:


function myfunc($x, $y = 0){
// compute ax2 + bxy + cy2
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2);
return $z;
}
3. Call/invoke a function:
We have defined our function successfully, how nice! Unfortunately, PHP does not execute such a function unless you call it in the main program or another function that is called by the main program. To call a function from main program, do:


function myfunc($x, $y = 0){
// compute ax2 + bxy + cy2
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2);
return $z;
}

$v1 = 5;
$v2 = 4;
$w = myfunc($v1, $v2);
echo $w;
// outputs 131
Now the function finally displays the result, good job good efforts! Note that we are passing $v1 and $v2 into the function, here $v1 replaces argument $x, $v2 replaces variable $y. We do not have to name our external variables the same name as the function arguments names in order to get our function to work properly. In fact, you can pass the same variable to multiple arguments, its perfectly valid to do this: myfunc($v1, $v1).

Assume we do not have a value for argument $y and instead, we want it to resume the default value 0? It cannot get any simpler, we omit the second argument:


function myfunc($x, $y = 0){
// compute ax2 + bxy + cy2
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2);
return $z;
}

$v = 5;
$w = myfunc($v);
echo $w;
// outputs 75
So it works, just as we expect. The missing argument $y takes on its default value 0, so the operation becomes essentially ax2. What if we actually want to omit $x? Well in this example we cannot do this since $x does NOT have a default value. Missing the argument $x when it has no default value will result in an error message:


Warning: Missing argument 1 for myfunc(), called in ...
Even if we give argument 1($x in this case) a default value, its still a bit tricky to omit the first argument. For this example we have two arguments, but we only supply one value, so we need to find a way to tell PHP that the argument is for $y not $x. The below technique explains how this is doable:


function myfunc($x = 0, $y){
// compute ax2 + bxy + cy2
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2);
return $z;
}

$v = 5;
$w = myfunc(null, $v);
echo $w;
// outputs 16
By passing null to the first argument it instantly assumes the default value, we are all good. Anyway you can see its not a good practice to have the first argument skipped while the rest arguments are not. When you encounter a situation like this, its better to switch the position of your function arguments.


4. Variable Scope in functions:
In section 2 I briefly introduced a concept called local variable, which are only available inside the function itself. In the example above, $a, $b and $c are all local variables in myfunc(), you cannot use print, echo or var_dump on these local variables from the main program. Also do not attempt to use them in further operations, this can create a fatal error.

Variables defined outside of the function are also inaccessible to the function. Let's say we have a variable $v3 defined in the main program, but it is not passed as an argument to myfunc(). The value of $v3 will be unavailable in our function, operations depending on it will inevitably fail:


function myfunc($x, $y = 0){
// compute ax2 + bxy + cy2
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2) + $v3;
return $z;
}

$v1 = 5;
$v2 = 4;
$v3 = 10;
$w = myfunc($v1, $v2);
echo $w;
// outputs 131, not 141!
The value of $v3 is not accessible in function myfunc(), and instead PHP assumes a default value 0 for any uninitialized variables in math operations. Our code has failed miserably.

We can of course re-declare the function to accept a third argument, then pass $v3 to the third argument. This will work, although a bit tedious if we have many functions depending on too many arguments. Another solution is to use the global keyword on $v3, which makes a global variable. Global variables are accessible in global scope, which means anywhere inside the script, they can be convenient at times:


function myfunc($x, $y = 0){
// compute ax2 + bxy + cy2 + v3
global $v3;
$a = 3;
$b = 2;
$c = 1;
$z = $a*pow($x, 2) + $b*$x*$y + $c*pow($y, 2) + $v3;
return $z;
}

$v1 = 5;
$v2 = 4;
$v3 = 10;
$w = myfunc($v1, $v2);
echo $w;
// outputs 141, as we desire
Global variables, however, are generally considered unsafe and poor programming practices. If you can modify the variable's value anywhere in the client code, it will inevitably bring up some security issues. The rule of thumb is to declare global variables when and only when they are supposed to be 'global'. Good examples are cookies, sessions, server variables, these are already pre-defined as global variables(or super-global variables) upon running our script.


5. Pass/return values by reference:
Now let's take a break from our function example and look at some interesting concept here. Usually a variable is a unique identity whose values do not get changed when another variable changes/reassigns. Consider the following example below:


$a = 5;
$b = $a;
$b = 10;
echo "a = {$a}";
echo "b = {$b}";
This will outputs a = 5 and b = 10, since b and a are different identities. Such variables are referred to as primitive types, each primitive variable is a different identity from each other even if they share the same value. What if we want $b to be an alias of $a instead? Well this will make $a and $b same identity, and it is achievable in PHP! All you have to do is to declare $b as reference of $a using the ampersand symbol:


$a = 5;
$b = &$a;
$b = 10;
echo "a = {$a}";
echo "b = {$b}";
This way $b becomes a reference to $a. If $a's value changes, so will $b. Similarly changing $b's value will result in $a being changed to the same value. Amazing isnt it?

This idea of reference can be extended to the usage of functions. You can pass variables by reference instead of by value. A good example is shown here:


function myvalue($x){
$x++;
}

function myrefer(&$x){
$x++;
}

$x = 5;
echo $x;
//outputs 5
myvalue($x);
echo "x = {$x}";
//outputs 5
myrefer($x);
echo "x = {$x}";
//outputs 6
In the function myvalue(), we pass variable to function by value. PHP treats local variable $x in function myvalue() and the $x in main script as distinct identities. For this reason, the value $x remains the same in our main script. If we pass by reference using the ampersand symbol, however, the local variable $x inside function myrefer() is a reference to our $x in main script. If one changes, the other will follow. This is why $x becomes 6 at the end.

We can also return from a function by reference. This is a bit tricky, the below program demonstrates the point of returning by reference:


$a = 0;
function myvalue(){
global $a;
return $a;
}

function &myrefer(){
global $a;
return $a;
}

$b = &myvalue();
$b++;
echo "a = $a, b = $b";
// outputs "a = 0, b = 1"

$c = &myrefer();
$c++;
echo "a = $a, c = $c";
// outputs "a = 1, c = 1"
Here $a is a global variable in the two functions, which makes its value readily available for us to manipulate. The function myvalue() behaves like a normal function, while function myrefer() has an ampersand before the function name. We try to assign reference to both $b and $c, but only the latter is successful. This is because the return value of &myrefer() is by reference, and thus $a is assigned the same identity as $c. This does not hold true for $b, since the function myvalue() does not return a reference. $b only gets the value from $a, but not $a itself.

You may wonder why we need to pass or return by reference. Well let's say we have several mysql void functions to execute, and we wish to keep track of the state of the mysql driver with a variable. Without passing/returning by reference, the variable we pass to mysql functions will never be able to record the state, since what we get from the end is the original value itself. In fact, this is better accomplished by using objects, which I will be writing lots of articles to describe what the heck they are. For now, just remember objects are reference types, they pass and return as reference by default. For this reason, theres no need to use cumbersome ampersand symbols if we use objects!


Alright, guess that's it for this tutorial. You must have been exhausted with this many weird concepts, havent you? PHP function is a subject that may requires weeks or even months to digest, even now there are still highly complex concepts of functions beyond my interpretation. Dont worry, we aint gonna reach that far in my tutorial about advanced functions.

I will be writing about anonymous functions, recursive functions, variable functions and a brief overview of PHP's built-in functions in the tutorial that follows Arrays and Strings. They aint that hard to comprehend so long as you understand the basics of functions very well. Until then, I hope you enjoy the latest release of Mysidia Adoptables, and have fun reading the tutorials I write. Take care.