Is php pass by reference or value?

TL;DR: PHP supports both pass by value and pass by reference. References are declared using an ampersand [&]; this is very similar to how C++ does it. When the formal parameter of a function is not declared with an ampersand [i.e., it's not a reference], everything is passed by value, including objects. There is no distinction between how objects and primitives are passed around. The key is to understand what gets passed along when you pass in objects to a function. This is where understanding pointers is invaluable.

For anyone who comes across this in the future, I want to share this gem from the PHP docs, posted by an anonymous user:

There seems to be some confusion here. The distinction between pointers and references is not particularly helpful. The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. [Using >= 5.3]

First principle: A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. [I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies]

2nd principle, and source of the most confusion: Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.

3rd principle: "&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset[]". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.

Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.

And here's the example they provide:



This will output the following:

array[3] {
  ["a"]=>
  int[1]
  ["b"]=>
  int[2]
  ["c"]=>
  &int[3]
}
array[3] {
  ["a"]=>
  int[4]
  ["b"]=>
  int[5]
  ["c"]=>
  &int[6]
}
array[3] {
  ["a"]=>
  int[1]
  ["b"]=>
  int[2]
  ["c"]=>
  &int[6]
}
int[6]

You could use this to allow a function to have read-write access to part of the array, while limiting it to read-only access for the rest of the array:

Jason Steelman

2 years ago

Within a class, passing array elements by reference which don't exist are added to the array as null. Compared to a normal function, this changes the behavior of the function from throwing an error to creating a new [null] entry in the referenced array with a new key.


This is in no way a "bug" - the framework is performing as designed, but it took careful thought to figure out what was going on. PHP7.3

phpnet at holodyn dot com

8 years ago

The notes indicate that a function variable reference will receive a deprecated warning in the 5.3 series, however when calling the function via call_user_func the operation aborts without fatal error.

This is not a "bug" since it is not likely worth resolving, however should be noted in this documentation.

diabolos @t gmail dot com

10 years ago



But this one will work :



So here is a workaround to have a default value for reference parameters :



And this scripts output is :

Array 1 Array
[
    [0] => test
    [1] => test2
    [indirect test] => test
]
_POST Array
[
    [indirect POST test] => test
]

Of course that means you can only assign default reference to globals or super globals variables.

Have fun

fladnag at zerezo dot com

5 years ago

Beware of using references with anonymous function and "use" keyword :

If you have a PHP version between 5.3 and < 5.3.10, "use" keyword break the reference :



A workaround is to use a copy of the reference variable in "use" keyword :

Chủ Đề