Heads up on PHP5 byValue/byReference function parameters

Hi everybody!

It’s been quite a long time since I wrote on my blog because I’ve been busy working and engineering several data models and software architecture for a risk management system.

During my work, I came back to the first real programming language I actually learnt, PHP, which I intend to use to create my UI.

When I started programming in PHP 9 years ago, I was using the PHP4 version which did not provide advanced object-oriented features as PHP5 does.

I don’t want to discuss the new features in PHP5 but there is an important change between the two versions that I was not completely familiar with in this language: the way PHP passes parameters to functions.

Back in PHP4, all parameters were passed by value, that is, that if you modified a parameter within the scope of the function, the changes occurred only within that scope and the parameter would remain unchanged in the upper level. In order to get the changes echoed in the upper scope, you would have to add “&” in front of the variable so that a “pointer” is passed to the function.

In PHP5, this is not true anymore and this is what I want to discuss in this post.

In the latest version, instances of a class are passed by reference; change will echo in the upper scope. “Native” types however, are still passe by values. This is the same behavior as in most object-oriented programming languages such as Java or C#.

However, PHP is not a strongly typed programming languages. It is hence difficult to know what is a “native” type and what isn’t.

Let’s consider the first example, an integer as in the following snippet:

function increment($i) {
    $i+=1;
}

$myVar=1;

increment($myVar);

echo $myVar; //Prints "1"

As you can see, the integer passed as a parameter hasn’t been altered by the function.

In order to make sure that the parameter changes in the upper scope, you have specify in the function definition that you want it to be passed by reference as follows:

function incrementByRef(&$i) {
    $i+=1;
}

incrementByRef($myVar);

echo $myVar; //Prints "2"

This is the behavior we would expect in any object-oriented programming language. However, what happens when we try with more “enhanced” types such as strings or arrays. In Java, strings (as opposed to char) are considered as objects, and hence would by passed by reference. On the other hand, strings are passed by value in C# as “string” is considered as a “native” type.

In PHP, they are also considered as “native” types as the following snippets demonstrates:

function concatstring($str1, $str2) {
    $str1.=$str2;
}

$string="Hello";

concatstring($string,"World");

echo $string; //Prints "Hello"

The same applies to PHP array which are very, very powerful structures comparable to C# dictionaries:

function changeIndex($array,$key,$value) {
    $array[$key]=$value;
}

$myArray=array("Hello"=>"Nothing");

changeIndex($myArray,"Hello","World");

print_r($myArray); //Prints "Array ( [Hello] => Nothing )"

What about classes then? Well as I already mentioned, instances of classes are passed by reference in PHP5 as shown in the following code:

class MyClass {
    public $MyInt=1;
    public $MyString="Hello";
    public $MyArray=array("Hello"=>"Nothing");
}

function increment2($class) {
    $class->MyInt+=1;
}

function concatstring2($class, $str2) {
    $class->MyString.=$str2;
}

function changeIndex2($class,$key,$value) {
    $class->MyArray[$key]=$value;
}

$myClass=new MyClass;

increment2($myClass);
concatstring2($myClass,"World");
changeIndex2($myClass,"Hello","World");

print_r($myClass)
// Prints "MyClass Object ( [MyInt] => 2 [MyString] => HelloWorld [MyArray] => Array ( [Hello] => World ) )"

Finally, one could argue that “manually” passing arguments by value might increase performance. However, after some testing I concluded that this assertion is wrong. First of all, the difference between the two is minimal, and most importantly, running the tests several times does not give the same method as the quickest every time!

Hence, forget about passing you parameters by reference manually when they are instances of classes in PHP5, it doesn’t look useful anymore.

See you next time!

Leave a Reply