When Is It Good to Use Pass by Reference in PHP

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.

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.'
?>

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.

Does the use keyword in PHP closures pass by reference?

No, they are not passed by reference - the use follows a similar notation like the function's parameters.

As written you achieve that by defining the use as pass-by-reference:

    $foo = function() use (&$var)

It's also possible to create recursion this way:

$func = NULL;
$func = function () use (&$func) {
$func();
}


NOTE: The following old excerpt of the answer (Jun 2012) was written for PHP < 7.0. As since 7.0 (Dec 2015) the semantics of debug_zval_dump() changed (different zval handling) the refcount(?) output of it differs nowadays and are not that much saying any longer (integers don't have a refcount any longer).

Validation via the output by not displaying $my_var changed (from 0) still works though (behaviour).

You can validate that on your own with the help of the debug_zval_dump function (Demo):

function bar(&$var)
{
$foo = function() use ($var)
{
debug_zval_dump($var);
$var++;
};
$foo();
};

$my_var = 0;
bar($my_var);
echo $my_var;

Output:

long(0) refcount(3)
0

A full-through-all-scopes-working reference would have a refcount of 1.

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);

PHP - why does passing by reference use the same amount of memory?

The answer is that objects cannot be passed by value. They are always passed by reference. The 'pass by reference' operator, '&', will do nothing other than wrap the object reference (i.e. a pointer) in a wrapper, then pass that new pointer.

As for the memory usage, there is no simple answer other than database query results seem to come with a lot of overhead, and you want to make your 'footprint' (i.e. any results returned from a database, or any variables) as small as possible.

Why Passing by Reference in PHP?

The reason that some other languages do not need to do this, is because they use objects: altering the state of an object is reflected to all references pointing to that object. If however you pass a primitive type in Java (like int) and you alter the parameter, the value will not be altered. The same story is for Strings since you cannot modify their state, you can only modify the reference passed as an argument. Note it is still pass-by-value, since you copy the reference which is basically what your method holds for an object.

PHP passes a string by value, which means - at least conceptually - a copy of the string is made before calling it.

Nevertheless pass-by-reference is sometimes considered dangerous. It is a concept that is used in C and C++ (and even in C#) but programming languages like Java do not allow this. You better use output to enable modifications of variables since it makes it syntactically explicit:

function airport($one,$two,$three,$four) {
if (!empty($one) || !empty($two) || !empty($three) ) {
$one = !empty($one) ? "Airline Name: $one<br>" :"Airline Name: PLEASE PROVIDE AIRLINE NAME<br>";
$two = !empty($two) ? "Flight Number: $two<br>" : "Flight Number: PLEASE PROVIDE FLIGHT NUMBER<br>";
$three = !empty($three) ? "Departure Airport: $three<br>" : "Departure Airport: PLEASE PROVIDE DEPARTURE AIRPORT<br>";
$four = !empty($four) ? "Comments: $four<br>" : "";
}
return array($one,$two,$three,$four);
}

and call it with:

list($airline_name,$flight_number,$departure_airport,$comments) = airport($airline_name,$flight_number,$departure_airport,$comments);

list is a special function where you call the variables by reference (yes, you do, it is actually a language construct as stated in the manual). The point is when you assign an array to a list construct, the elements in the array are assigned element-wise to the variables specified in the list. For example (taken from here):

list($drink, $color, $power) = array('coffee', 'brown', 'caffeine');

is equivalent to:

$drink = 'coffee';
$color = 'brown';
$power = 'caffeine';

it is thus more or less the opposite of array: you split the array into elements and perform element-wise assignment.


Using list, it is clear to everyone these variables will change. Furthermore you do not have to look into the function signature to know whether a variable will change: it won't. If you change your mind and want to set other variables, that's easy as well.

Why are my variables passed by reference?

PHP passes all object by reference, by default.

More informations here : http://php.net/manual/en/language.oop5.references.php



Related Topics



Leave a reply



Submit