Get your FREE 30 page Developing SOLID Applications guide!

How To Write A Function In PHP

Out Of Date Warning

Languages change. Perspectives are different. Ideas move on. This article was published on October 12, 2009 which is more than two years ago. It may be out of date. You should verify that technical information in this article is still current before relying upon it for your own purposes.

PHP allows developers to write a variety of different styles of code: procedural, object-oriented, or simply scripts. This flexibility makes PHP easy to learn, and also means that new developers to PHP may not be programmers in other languages.

For new developers, especially developers who have never been programmers before, moving from writing simple scripts to writing functions is a process that takes time. I developed in PHP for years before I wrote a single function. I also never found a comprehensive tutorial on how functions work, or how to write them. There’s documentation in the manual, but it’s a bit hard to grasp if you’re new. This article is about writing functions.

For starters, what is a function? A function is a collection of code that is available for use and reuse repeatedly throughout a particular script or application. You’re probably already familiar with functions because you probably use them in PHP. If you’ve used print() or mysql_connect() you’ve used a function. Both of these functions encapsulate other code (in their case, core PHP code written in C), and allow you to accomplish certain tasks.

Matthew Turland equates writing a function to tasking a junior level employee. After describing a short name for a particular task, you teach the scope of that task, and then can direct the task to be executed at any time.

The beauty of functions is that you don’t have to rewrite the same code over and over again. Once it’s encapsulated in a function, that function provides a shortcut to executing the code you’ve defined. This is a pretty cool tool when you think about it.

For example, let’s say that you establish a MySQL connection every single page. You could do the following on every page:

$connection = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('mydatabase');

Or, you can write a function that does this, and call the following on every page:

$connection = myConnectionFunc();

Which would be easier for you? Well, the second one of course. Let’s learn how we did that.

The source code behind myConnectionFunc() is pretty basic. If you don’t understand the syntax entirely from looking at it, don’t worry. I will explain.

<?php

function myConnectionFunc($host = 'localhost', $user = 'user', $pass = 'pass', $database = 'mydatabase')
{
$conn = mysql_connect($host, $user, $pass);
mysql_select_db($database);
return $conn;
}

That may look quite complicated but once you understand the syntax, it’s not all that complicated at all. We’ll come back to this example once we know a little bit more about functions.

All Functions Share These Characteristics

For starters, all functions share certain characteristics. The function definition starts with the word “function”, followed by the name of the function, an opening parenthesis, any arguments, and a closing parenthesis. You must also include curly braces to delimit the body of the function. Here is the most basic function you can have in PHP:

function basic()
{
}

All functions should share these qualities. They are required by the PHP engine to determine that a function has been defined. Without them, you will get a syntax error.

Function Bodies

A function body can contain any user-defined (that’s functions you write) or internal (that’s functions PHP provides by default) functions, structures, and code that you like. Remember: functions serve to encapsulate the functionality you want to express, meaning that a function can be called repeatedly to accomplish a certain task. For example, a function can look like this:

function iterateArray($array)
{
foreach($array as $item)
{
$newArray[] = 'Iterated: ' . $item;
}
return $newArray;
}

What you put in the body is largely up to you. There are few (if any) restrictions. Bear in mind, that there are best practices; you should make yourself aware of them through the PHP manual and further reading.

Function Scope, Arguments, and Return Values
One of the most important things (and most difficult concepts to grasp) about functions is the concept of a function’s scope.

Functions don’t know about what is going on outside the function. They don’t know what variables have been defined, or what is going on around your application at the time you invoke them. They only know about the information they have been given, and the contents of their bodies. This behavior is necessary because if functions were aware of the “global scope” (all the variables and information that is defined in your application), you could get very unpredictable behavior. Instead, they are “dumb code units”, as Matthew Turland describes it.

Similarly, when a function ends, anything that happened inside of it is forgotten. This is to prevent the function from improperly altering behavior in your application, which would also result in some very strange bugs.

But this creates a big problem: how on earth do we get information into and out of a function?

To get information in, we pass the function some arguments. An argument is a variable that exists between the parenthesis in the declaration. See the example below, with the variable $argument:

<?php

function basic($argument)
{
echo $argument;
}

basic('hello world!'); // outputs 'hello world!'

By placing a variable called $argument between the parenthesis, we have told the function “this variable will be available for your use.” The function then can access that variable.

But what happens when we do this?

$argument = 'Hello World.';
$var = 'Hello Brandon.';
basic($var);

What will the output be? The output will be “Hello Brandon”. You might be scratching your head and saying “wait a minute! $var isn’t $argument!” In fact, it is. See, the beauty of a function is that it doesn’t care what’s going on outside of itself; it only cares about its own little world. The variable $argument, as defined in the function, is a placeholder for ANY value we want to give it. That variable need not be named $argument. The function doesn’t care if the global scope has a variable named $argument; it only cares about what you give its placeholder.

You can have multiple arguments. You only need to separate them by a comma. Convention says that you should add a space after each comma, but that’s entirely up to you and your own personal coding standard; it is not required by the parser.

How do we get information out of a function? In the previous example, we used the echo() construct to directly output our statement, but this wouldn’t work if we had assembled an array, for example. Since everything inside a function is destroyed when the function’s execution ends, we’ve got to use a different method to get information out of a function: the language construct ‘return‘.

This language construct allows us to return a value from the function. It also has the benefit of halting execution of the function, meaning we can use it to return a value early if we’re done executing the function. You can return any PHP type, including the value of a variable. Note that returning a variable does not place that variable into the global scope; it returns the value only. For example:

<?php

function basic($argument)
{
$var = $argument;
return $var;
}

This does not inject a variable named $var into the global scope; it returns whatever the value of $var happens to be.

Default Argument Values

You may have noticed in our initial example that I added an equals sign and a string value after defining the arguments. This is a perfectly valid technique, which adds a default value to each of the arguments. You may assign a default value to some, all, or none of your arguments, as you see fit.

The benefit of default argument values is that it allows you to call the function without having to set default values each time. For example, in our initial function the login credentials are unlikely to change. However, by permitting arguments, you are allowed to connect to a different database or database server. If you assign values to the arguments when you call the function, they automatically override the default values in the definition.

Bear in mind that if you want to assign some of your arguments default values, it is best to place these arguments towards the end of your function signature. The reason is that if you place them at the front, you will have to assign them a null value. For example:

<?php

function badFunc($var1 = false, $var2)
{
return ($var1 == $var2);
}

$myvar = badFunc(null, true);

function goodFunc($var2, $var1 = false)
{
return ($var1 == $var2);
}

$myvar = goodFunc(true);
$mysecondvar = goodFunc(true, true);

In the first example, because we placed the optional argument in the front, we had to give it a value in order to define the second, required value. But in the second function, we reverse the order of the arguments, making our function easier to use. This is highly recommended development practice for PHP.

Returning Multiple Values From A Function

PHP does not allow for the return of two values from a function. This is a limitation of the language’s structure. However, it is possible to return an array from a function, which results in similar functionality. For example:

<?php

function returnArray($var1, $var2, $var3)
{
$array = array($var1, $var2, $var3);
return $array;
}

This will return an array containing the values for $var1, $var2 and $var3. This makes returning multiple values easier. You can also return objects, if you like. This is considered an acceptable practice.

Bringing The Global Scope Into Your Function

Warning: The behavior discussed in here may result in an unpredictable behavior in your PHP applications. There are very valid reasons for using this functionality, but they are few and far between. The information is provided for completeness only, and should not be used unless you fully understand why you’re using it. Using this behavior probably means that a refactoring of your code is in order.

It is possible to bring parts of the global scope into your application by using the keyword ‘global’. The global keyword allows you to define variables that exist in the global scope as variables that also exist in the function’s internal scope.

For example:

<?php

$string = 'my string';

function printString()
{
global $string;
echo $string;
}

printString(); // outputs 'my string'

In this example, we bring the global variable $string into our function and then print it out. This example is perfectly benign; however, there are some caveats. The first caveat is that if the variable $string did not exist in the global scope, this function would output absolutely nothing. The second caveat is that by including the variable as a global variable, any changes that are made to that variable are reflected in the global scope.

This is a very bad programming practice. Typically, if you are finding it necessary to pass variables into a function through the global scope, you should consider how your code can be refactored so that this is no longer necessary.

Passing By Reference

Warning: Passing variables by reference is a very powerful, and potentially dangerous, behavior. Additionally, it makes debugging and testing difficult. Always consider carefully your reasons for passing or returning by reference, and consider refactoring to make it unnecessary.

When you define arguments for a normal function, these arguments are given to the function in a fashion that is known as “by value.” Essentially, PHP copies the value of the variable, and then gives it to the function. Changes to that copy are not reflected in the global scope.

There is another way to pass to and return from functions: by reference. Passing “by reference” means that rather than copying the value, you are tying the two variables together. When you alter the value of one variable, you alter the value of the second. For example:

<?php

$var1 = 'a';
$var2 =& $var1;
$var2 = 'b';

echo $var1; //outputs 'b'

In this example, we attach the two by reference, making our change to $var2 reflected in $var1. You can also do this with functions:

<?php

function addOne(&$num)
{
	$num++;
}

$var = 6;
addOne($var);

echo $var; // Outputs 7

Note that even though we did not return anything from addOne(), the $var value was affected in the global scope. This is because we passed it by reference when we defined the function. This tied the value of $var to $num, and when we incremented $num, we also incremented $var.

Passing by reference should always be done when you define the function. You should never pass by reference at runtime. For example, the following syntax would be unacceptable:

function addOne($num)
{
	$num++;
}

$var = 6;
addOne(&$var);

While this behavior will not break in PHP 5, it will probably not be allowed in PHP 6, and will emit a nasty warning if you do it.

Bear in mind that when passing by reference, a variable is the only thing you may pass. You cannot pass an expression or any other value to a function that expects a variable passed by reference.

With regards to references as a programming practice, be aware that references aren’t doing what you think they are behind the scenes. While they have very limited application, you should understand the implications, and more often than not, you will want to pass by value.

Conclusion

By now, you’ve had a chance to be exposed to some of PHP’s most common function behavior and, hopefully, will be able to write functions yourself. Functions provide a powerful way to encapsulate and extend your code, share common functionality without writing it for each occasion, and improving your ability to prevent bugs.

This blog entry implements The Beginner Pattern.

Write better object oriented PHP today.

Object oriented programming always leaves you with a headache. What if you could master it instead?

Get the book now! »

Niels wrote at 10/12/2009 1:53 am:

Scripting is not a programming paradigm[1] like object-orientation or procedural ;-) It expresses just the fact that programs of a scripting language need not be compiled before execution.

1: http://en.wikipedia.org/wiki/Programming_paradigm

Flyingmana wrote at 10/12/2009 3:21 am:

I think its important to say, that objects since PHP 5 always are passed by reference.

Ulf Wendel wrote at 10/12/2009 4:20 am:

… and if you are beginner and use ext/mysql you code crap. The current MySQL extension is ext/mysqli. The php.net manual tells you why.

Sky wrote at 10/12/2009 10:48 am:

Hello

Why do you use this :
function goodFunc($var2, $var1 == false)

When you can use this :
function goodFunc($var2, $var1 = false)

The default value of a variable is a definition, not a comparaison.

Sry if i got something whrong.

Brandon Savage (@brandonsavage) wrote at 10/12/2009 10:58 am:

Sky, you caught a mistake I made and didn’t catch when I was proofreading. Good eye!

I’ve fixed the mistake.

Bruce Weirdan wrote at 10/12/2009 5:32 pm:

> Bear in mind that if you want to assign some of your arguments
> default values, it is best to place these arguments towards the
> end of your function signature. The reason is that if you place
> them at the front, you will have to assign them a null value.
Unlike you imply this will not have the same effect as not passing the argument, as illustrated by the following example:

[weirdan@home ~]$ php -r ‘echo PHP_VERSION . PHP_EOL; function a($b = false, $c = false) { var_dump($b, $c); } a(null);’
5.2.8
NULL
bool(false)
[weirdan@home ~]$

As you can see, $b is null inside the function, just what was passed to the function.

Your goodFunc example have a syntax error:
function goodFunc($var2, $var1 == false) // <— it should be $var1 = false

Bruce Weirdan wrote at 10/12/2009 5:36 pm:

> I think its important to say, that objects since PHP 5 always are passed by reference.

Well, it’s not true. In fact Brandon linked in this very blog post to the article by Sara Golemon that specifically deals with this very misconception.

Brandon Savage (@brandonsavage) wrote at 10/12/2009 5:39 pm:

Hey Bruce, I fixed that syntax error earlier, and it looks to be fixed in my version. Are you seeing it differently?

Bruce Weirdan wrote at 10/12/2009 5:55 pm:

> Hey Bruce, I fixed that syntax error earlier, and it looks to be fixed in my version. Are you seeing it differently?
No, I just had this tab opened since morning, and forgot to refresh prior to posting.

Samuel Folkes (@SamuelFolkes) wrote at 10/26/2009 12:13 am:

Excellent article. I just have one teensy tiny problem: print() is actually not a function. Its a language construct. That aside, good work!

Brandon Savage (@brandonsavage) wrote at 10/26/2009 5:48 am:

I always make the mistake of confusing print() with a function because it has a return value, unlike echo(). My bad!