When to Pass-By-Reference in PHP

When to pass-by-reference in PHP

If you mean to pass a value (so the function doesn't modify it), there is no reason to pass it by reference : it will only make your code harder to understand, as people will think "this function could modify what I will pass to it — oh, it doesn't modify it?"

In the example you provided, your do_my_hash function doesn't modify the value you're passing to it; so, I wouldn't use a reference.

And if you're concerned about performance, you should read this recent blog post: Do not use PHP references:

Another reason people use reference is
since they think it makes the code
faster. But this is wrong. It is even
worse: References mostly make the code
slower! Yes, references often make
the code slower - Sorry, I just had to
repeat this to make it clear.

Actually, this article might be an interesting read, even if you're not primarily concerned about performance ;-)

Are PHP Variables passed by value or by reference?

It's by value according to the PHP Documentation.

By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.

To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.

<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}

$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>

When is it good to use pass by reference in PHP?

The following does not apply to objects, as it has been already stated here. Passing arrays and scalar values by reference will only save you memory if you plan on modifying the passed value, because PHP uses a copy-on-change (aka copy-on-write) policy. For example:

# $array will not be copied, because it is not modified.
function foo($array) {
echo $array[0];
}

# $array will be copied, because it is modified.
function bar($array) {
$array[0] += 1;
echo $array[0] + $array[1];
}

# This is how bar shoudl've been implemented in the first place.
function baz($array) {
$temp = $array[0] + 1;
echo $temp + $array[1];
}

# This would also work (passing the array by reference), but has a serious
#side-effect which you may not want, but $array is not copied here.
function foobar(&$array) {
$array[0] += 1;
echo $array[0] + $array[1];
}

To summarize:

  • If you are working on a very large array and plan on modifying it inside a function, you actually should use a reference to prevent it from getting copied, which can seriously decrease performance or even exhaust your memory limit.

  • If it is avoidable though (that is small arrays or scalar values), I'd always use functional-style approach with no side-effects, because as soon as you pass something by reference, you can never be sure what passed variable may hold after the function call, which sometimes can lead to nasty and hard-to-find bugs.

  • IMHO scalar values should never be passed by reference, because the performance impact can not be that big as to justify the loss of transparency in your code.

Passing by reference vs. passing by value

Let's pretend $x is a piece of paper with 5 written on it.

function sum($y) {
$y = $y + 5;
}

Here $y is the value of what you have written. You add 5 to such value in your mind, but the note is left untouched.

function sum(&$y) {
$y = $y + 5;
}

With the reference operator (&$y), you pass the very paper to the function, and it overwrites what's written on it.


For primitive values like numbers, I wouldn't bother and always return the value you want:

function valuePlusFive($x) {
return $x + 5;
}

$x = 5;
$x = valuePlusFive($x);

Benefit of passing by reference? (php)

Passing by reference is faster. PHP5 do pass objects by reference by default. I think under PHP 5.3, you still have to do $obj = &new Object();, but I could be wrong about that.

PHP5 do not pass array by reference. If you want to modify them in a function, you need to pass by reference.

Passing by value means that every single value is copied. For example, if you pass an array by value, it copies the array to a different memory location and every single element in it.

Do I need to use the ampersand in PHP 5.5.X and above anymore?

The reason different articles seem to be saying different things is that they are talking about different kinds of pass-by-reference.

The main thing that determines if a parameter should be passed by reference is the function signature itself, and the fundamentals of this have not changed since PHP 4. Consider this example:

function foo( $by_value, &$by_reference ) { /* ... */ }

$a = 1; $b = 2;
foo( $a, $b );

Here, the outer variable $a is being passed to the function by value, as though it is being assigned as $by_value = $a; - changes to $by_value cannot affect $a. The variable $b however is being passed by reference; just like an assignment of the form $by_reference =& $b; this means that there is one variable referenced by two names, and any assignment to one will act as an assignment to both.

If you pass an "ordinary" value (a string, number, or array) by value, its value is just copied to the new variable. As of PHP 5: If you pass an object by value, however, something slightly different happens - the "value" copied is just a pointer to the same object. This means that if $a were an object, you could call $by_value->some_property = 42; and $a->some_property would also be 42. However, if you assigned some new value to $by_value, it would still not affect $a.

Until PHP 5.4, there was an extra way to pass a parameter by reference, which was to "force" the reference behaviour at call-time. This meant that you could write foo(&$a, &$b); and "capture" changes made to $by_value inside the foo() function. Relying on this was generally a bad idea, and so it was removed. (It landed in 5.4 because it was intended for removal in PHP 6, but that project was put on indefinite hold, with the smaller changes landing in 5.3 and 5.4).

Finally, functions can return a variable by reference (as discussed in the manual here). This is a little fiddly, as it actually requires you to put & in two places: at the beginning of the function declaration, to say that return should mean "return this variable reference" not "return this value"; and in the code calling it, to assign a variable to that reference, rather than just copying its value. Here's a silly example which combines a reference parameter with a reference return (the two do not have to go together, it's just an example):

function &bar(&$some_param) { return $some_param; }
$a = 1;
$b =& bar($a);
// $b and $a now point at the same variable, not just the same value
// it was passed into and out of a function, and assigned to a new variable,
// but all those operations were by reference

Note that many people mistakenly believe that passing a variable by reference will give them a performance benefit, and this was often their only reason for using call-time pass-by-reference. This is in fact usually wrong, as the Zend Engine which powers PHP uses a technique called "copy on write" to leave multiple variables which happen to have the same value pointing at the same piece of memory, even if they are not bound up as references. In fact, reference assignment generally defeats this optimisation, due to the way the engine tracks which variables are in the copy-on-write state.

Pass by reference in function for isset() & empty()

When a function takes a by-reference argument, warnings about it being undefined are disabled at the time of the call. This is because the function might be used to assign the variable, so it's not an error to pass an undefined variable, or nonexistent index. For instance, suppose you had a function like:

function setTo3 (&$arg) {
$arg = 3;
}

setTo3($array[1]);

There's no reason to warn about $array[1] not being defined, because setTo3() never uses the argument's value.

What happens when you pass an object by reference, in php, under the hood?

Any variable that holds an object is not holding the object directly. It holds an identifier of the object. Imagine it as the object living somewhere in an object pool having a number attached to it, e.g. #5. All the variable contains is "object #5". PHP knows that the variable refers to an object and that it's supposed to be object #5.

Whenever you work with such a variable holding an object reference, PHP looks up the referenced object from the object pool.

When you pass such a variable into a function, PHP makes a copy of that reference. There are then two variables holding the content "object #5". Not the object itself has been copied, just this tiny note which says "object #5".

When you pass such a variable into a function by reference, well, you're passing that note "object #5" by reference. PHP won't make a copy of it. But it's still just a variable saying "object #5", so when you're trying to work with it, PHP will look up the object from the pool.

This object reference mechanism is not the same as the & pass-by-reference mechanism. The object reference mechanism works exactly the same as all other pass-by-value operations; it's just that a value which represents a reference to an object is always being treated in a specific way (PHP has to look up the actual object elsewhere).



Related Topics



Leave a reply



Submit