Content:
Passing by reference is a feature which allows a variable to be modified directly.
It’s similar to the use of pointers in languages such as C
, as only one copy of a variable exists. Here, it can provide a decent performance boost if used correctly.
In PHP, though, the use-case is somewhat different.
This article will explain how to explicitly pass-by-reference in PHP, and why you generally should avoid doing so.
How to Pass By Reference
To begin, we’ll introduce passing by reference in PHP.
To pass a value by reference, append a & to the variable name.
function add(int &$num) {...}
This should be added on the receiving end of your code, for example, inside the function definition. Using this notation in the function call is invalid.
add(&$num); # error
Pass-by-reference can also be used in loops.
foreach ($input as &$ref) {...}
How Values are Usually Passed
To see why you’re unlikely to need to pass-by-reference, consider how PHP passes values by default.
PHP uses a process called ‘Copy on Write’, or CoW for short.
When a variable is passed to a function, it is initially passed by reference. This is implicit – it occurs without being enforced in your code.
The function receiving the variable is allowed to look at the value it contains.
function add(int $num) {
echo $num; # 5
}
$num = 5;
add($num);
As soon as the function attempts to modify this variable, PHP creates a fresh copy for the function to modify. The calling function retains the original copy, with the original value intact. Out function is now effectively using pass-by-value.
This is an efficient way of passing variables, without creating unnecessary copies of values when they’re not needed.
Here’s an example of this in action.
function add(int $num, int $num2)
{
$num += $num2;
return $num;
}
$num = 5;
$num2 = 2;
echo add($num, $num2); # 7
In this function, the $num
and $num2
variables are passed into the function.
$num += $num2;
This line adds the second value onto the first. The code does not assign a new variable to the result.
At this point, PHP creates a new copy of $num
in memory to operate on. It’s this new copy which has $num2
added to it.
The result is that two different $num
variables exist – the one inside the function, with a value of 7, and the one outside the function, with a value of 5.
Ideally, different variable names should be used to make this code cleaner, but it demonstrates well PHP’s CoW technique.
When to Pass By Reference
Most of the time, this default behaviour will be enough.
When calling a function, it’s generally clearer to operate on a value and assign the result to a new variable (even if you’re reusing a variable name).
$num = add($num, $num2);
add($num, $num2);
It’s immediately obvious here that $num
has been assigned to the result of the function, and from now on contains the updated value. If $num
is instead passed by reference, $num
would change, without it being obvious why.
There’s also little, if anything at all, to be gained by explicitly forcing pass-by-reference yourself.
There are situations, however, where it’s desirable to pass by reference.
The following code loops through and flattens an array, converting any nested arrays to JSON.
foreach ($row as &$field) {
if (is_array($field)) {
$field = json_encode($field);
}
}
Passing by reference when looping through an array allows data in the original array to be edited directly.
It would be possible to obtain a similar result by creating a second array to store the output. This would have the effect of both making the code more complex, while potentially impacting performance due to the addition of a second array.
Passing by reference in a loop avoids some of the issues mentioned previously. This code can’t be called from elsewhere, so it only runs where it’s defined.
Conclusion
Passing by reference is a feature which should only be used when it makes sense to do so. It’s always possible to rewrite a function to return a value, instead of modifying the original directly.
If your code substantially alters a value, or returns a totally different value (for example, creating a hash of the original), it’s advisable not to pass by reference. Code clarity is important, and modifying one value to hold something totally different will only create confusion.
That said, it does have its uses. In fact, many internal PHP functions use pass by reference (for example, array_sort()
).
Consider the impact on both application speed and the readability of your code before choosing to pass by reference.