In PHP, the difference between passing by value and passing by reference is one of those topics that can be treated as either an advanced concept or a basic one you need to understand early. For beginners, it also comes up often in interviews. What makes it confusing at first is that the two behaviors can look similar until you see what actually gets changed.
A simple way to think about it is this:
Passing by value is like making a copy. Imagine I own a house and I give you the building materials to construct another house exactly like mine. What you do in your house has no effect on mine, and what I do in mine has no effect on yours. They are separate.
Passing by reference is different. Instead of giving you materials to build a new house, I give you a key to my house. Now both of us can enter the same house. Any change you make inside it affects the very same place I use.
What each one means
Pass by value: any modification made to the value inside a function is ignored outside that function. In practical terms, PHP passes a copy of the value. The target gets its own equivalent memory space.
Pass by reference: changes made inside the function are visible outside it as well. The argument is effectively passed by address, so the formal parameter and the original variable refer to the same thing. They only have different names.
1. Passing by value
<?php
$param1=1; //定义变量1
$param2=2; //定义变量2
$param2 = $param1; //变量1赋值给变量2
echo $param2; //显示为1
?>
Here, $param2 receives the value of $param1, not its reference. So $param2 becomes 1, but the two variables remain independent.
2. Passing by reference
<?php
$param2=1; //定义变量2
$param1 = &$param2; //将变量2的引用传给变量1
echo $param2; //显示为1
$param1 = 2; //把2赋值给变量1
echo $param2; //显示为2
?>
This time $param1 does not get a separate copy. It points to the same value as $param2. Because both names refer to the same underlying data, changing $param1 also changes $param2.
3. Passing a value into a function
<?php
//传值
$param1 = 1; //定义变量1
function add($param2) //传参数
{
$param2=3; //把3赋值给变量2
}
$param3=add($param1); //调用方法add,并将变量1传给变量2
echo '<br>$param1=='.$param1.'<br>'; //显示为$param1==1
echo '<br>$param2=='.$param2.'<br>'; //显示为$param2== 因为$param2是局部变量,所以不能影响全局
echo '<br>$param3=='.$param3.'<br>'; //显示为$param3== 因为add方法没有返回值,所以$param3为空
?>
When add($param1) is called, the function receives only a copy of $param1. Inside the function, $param2 becomes 3, but that change stays local.
So after the call:
$param1is still1$param2cannot be accessed globally because it is a local variable inside the function$param3is empty because the function does not return anything
4. Passing a reference into a function
<?php
//传值
$param1 = 1; //定义变量1
function add(&$param2) //传参数
{
$param2=3; //把3赋值给变量2
// return $param2; //返回变量2
}
echo '<br>$param1=='.$param1.'<br>'; //显示为$param1==1 没对变量1进行操作
$param3=add($param1); //调用方法add,并将变量1的引用传给变量2
echo '<br>$param1=='.$param1.'<br>'; //显示为$param1==3 调用变量过程中,$param2的改变影响变量1,虽然没有return
echo '<br>$param2=='.$param2.'<br>'; //显示为$param2== 因为$param2局部变量,所以不能影响全局
echo '<br>$param3=='.$param3.'<br>'; //显示为$param3== 如果把方法里面的return注释去掉的话就为$param3==3
?>
The key difference is the & in function add(&$param2). That means $param2 refers to the original $param1.
As a result:
- before calling the function,
$param1is1 - inside the function, assigning
3to$param2also changes$param1 - after the call,
$param1becomes3even though the function does not explicitly return it $param2is still a local variable name, so it cannot be accessed outside the function scope$param3remains empty unless thereturn $param2;line is enabled
5. Passing by reference and returning by reference
<?php
//传引用
$param1 = 1;
function &add(&$param2)
{
$param2 = 2;
return $param2;
}
$param3=&add($param1);
$param4=add($param1);
echo '<br>$param3=='.$param3.'<br>'; //显示为$param3==2
echo '<br>$param4=='.$param4.'<br>'; //显示为$param4==2
echo '<br>$param1=='.$param1.'<br>'; //显示为$param1==2 调用变量过程中,$param2的改变影响变量1
$param3++;
/*下面显示为$param1==3,这是因为$param2和$param1引用到同一个地方,
\* 返回值前面加了地址符号还是一个引用$param3=&add($param1);
\* 这样$param3,$param2和$param1引用到同一个地方,当$param3++;时,
\* $param1会被改变*/
echo '<br>$param1=='.$param1.'<br>';
$param4++;
/* 下面显示为$param1==3,这里为什么是3而不是4呢,这是因为返回值前面没有
\* 地址符号,它不是一个引用所以当$param4改变时不会影响$param1*/
echo '<br>$param1=='.$param1.'<br>';
?>
This example goes one step further. The function parameter is passed by reference, and the function itself also returns by reference.
That creates an important distinction between $param3 and $param4:
$param3=&add($param1);means$param3receives a reference to the same value$param4=add($param1);means$param4only receives the returned value, not a bound reference
So the sequence works like this:
add($param1)sets$param1to2$param3is linked to the same underlying value as$param1- increasing
$param3with$param3++also changes$param1, so$param1becomes3 $param4is only a normal value copy, so$param4++does not affect$param1- that is why
$param1stays3instead of becoming4
This is the part that often trips people up: passing by reference and returning by reference are related, but they are not the same thing.
What about performance?
With small amounts of data, the difference is usually negligible. But when the amount of data becomes large, pass-by-value can be more expensive because PHP has to copy the value. For large strings and objects in particular, that copying cost can be significant.
Passing by reference avoids copying the value itself, so in some cases it can be helpful for performance.
The practical takeaway is simple: if you need isolation, use value passing. If you want a function or variable assignment to operate on the same underlying data, use references carefully. The behavior is powerful, but if you do not clearly track what is shared and what is copied, it becomes easy to change a variable without realizing where the change came from.