Pass by Reference
What Is Pass by Reference? In simple terms: Normally, a function receives a copy of each argument, so changes inside the function do not affect the caller. When a parameter is passed by reference , th
What Is Pass by Reference?
In simple terms: Normally, a function receives a copy of each argument, so changes inside the function do not affect the caller. When a parameter is passed by reference, the function works on the caller's original variable, and any change it makes is visible after the call.
Technically: Prefixing a parameter with & in the function declaration makes it a reference to the variable passed as the argument. The parameter and the caller's variable become two names for the same value.
function addTax(float &$price, float $ratePercent): void // & marks $price as a reference
By Value vs By Reference
| By Value (default) | By Reference (&) | |
|---|---|---|
| What the function receives | A copy of the value | The caller's variable itself |
| Changes inside the function | Affect only the copy | Affect the caller's variable |
| What can be passed | Any expression | Only a variable (or array element/property) |
| How results usually leave the function | return | Modifying the parameter |
Syntax
function functionName(Type &$parameter)
{
$parameter = /* new value */; // changes the caller's variable
}
The & appears only in the declaration. The call looks like a normal call: functionName($variable);.
Example
<?php
function addTaxByValue(float $price, float $ratePercent): void
{
$price = round($price * (1 + $ratePercent / 100), 2);
}
function addTax(float &$price, float $ratePercent): void
{
$price = round($price * (1 + $ratePercent / 100), 2);
}
$a = 1000.0;
addTaxByValue($a, 18);
echo "By value: $a\n";
$b = 1000.0;
addTax($b, 18);
echo "By reference: $b\n";
Output
By value: 1000
By reference: 1180
How It Works
addTaxByValue()receives a copy. It changes the copy, which is discarded when the function ends, so$ais unchanged.addTax()declares&$price, so$priceis$binside the function. Assigning to$priceassigns to$b.
Built-in Functions That Use References
You have probably already used pass by reference through PHP's own functions:
<?php
// 1. Sorting modifies the array in place
$names = ['Ravi', 'Asha', 'Bala'];
sort($names);
echo implode(', ', $names) . "\n";
// 2. preg_match() fills the $matches array
preg_match('/(\d{4})-(\d{2})-(\d{2})/', 'Due on 2026-10-15', $matches);
echo "Year {$matches[1]}, month {$matches[2]}, day {$matches[3]}\n";
// 3. str_replace() reports how many replacements were made
$text = str_replace('cat', 'dog', 'cat & cat', $count);
echo "$text ($count replacements)\n";
// 4. array_push() adds to the original array
$queue = ['task-1'];
array_push($queue, 'task-2', 'task-3');
echo count($queue) . " tasks queued\n";
Output
Asha, Bala, Ravi
Year 2026, month 10, day 15
dog & dog (2 replacements)
3 tasks queued
In the PHP manual, reference parameters are marked with & in the signature — for example, sort(array &$array, int $flags = SORT_REGULAR): true and preg_match(string $pattern, string $subject, array &$matches = null, ...). Recognizing this & tells you that the function will modify the variable you pass.
Only Variables Can Be Passed by Reference
A reference must point to something that can be changed — a variable, an array element, or an object property. Literal values and function results have nowhere to store the change.
Passing a Literal
<?php
function addTax(float &$price, float $ratePercent): void
{
$price = round($price * (1 + $ratePercent / 100), 2);
}
addTax(500.0, 18);
Result: PHP throws an Error stating that argument #1 ($price) could not be passed by reference. A literal 500.0 is not a variable, so there is no place to store the new value.
Passing a Function Result to a Built-in Reference Parameter
<?php
$lastPart = end(explode(',', 'red,green,blue'));
echo $lastPart;
Output
PHP Notice: Only variables should be passed by reference in /path/script.php on line 2
blue
end() takes its array by reference (it moves the array's internal pointer), but explode(...) returns a temporary value. PHP still returns the right answer but warns about it. Store the result in a variable first:
<?php
$parts = explode(',', 'red,green,blue');
echo end($parts);
Output
blue
Modifying Arrays in Place
A common use of references is updating an array passed by the caller:
<?php
function addToCart(array &$cart, string $item, int $quantity = 1): void
{
$cart[$item] = ($cart[$item] ?? 0) + $quantity;
}
$cart = [];
addToCart($cart, 'Pen', 2);
addToCart($cart, 'Notebook');
addToCart($cart, 'Pen');
print_r($cart);
Output
Array
(
[Pen] => 3
[Notebook] => 1
)
Each call modifies the caller's $cart directly. $cart[$item] ?? 0 starts the quantity at 0 for new items.
The Alternative: Return a New Array
<?php
function withItem(array $cart, string $item, int $quantity = 1): array
{
$cart[$item] = ($cart[$item] ?? 0) + $quantity;
return $cart;
}
$cart = [];
$cart = withItem($cart, 'Pen', 2);
$cart = withItem($cart, 'Notebook');
$cart = withItem($cart, 'Pen');
print_r($cart);
The output is identical. The returning version makes the change visible at the call site ($cart = ...), whereas addToCart($cart, ...) hides the fact that $cart is modified. That visibility is why many developers prefer returning values.
Returning Several Values Without References
References are sometimes used to "return" multiple values. An array with destructuring is usually clearer:
<?php
function splitName(string $fullName): array
{
$parts = explode(' ', trim($fullName), 2);
return [$parts[0], $parts[1] ?? ''];
}
[$first, $last] = splitName('Priya Sharma');
echo "$last, $first\n";
Output
Sharma, Priya
The function's signature shows exactly what it produces, and the caller chooses the variable names.
References and Objects
Objects are passed as handles, so a function can change an object's properties without & (see Function Arguments). The & matters only when the function replaces the whole object:
<?php
function replaceWithoutReference(stdClass $user): void
{
$user = new stdClass();
$user->name = 'Replaced';
}
function replaceWithReference(stdClass &$user): void
{
$user = new stdClass();
$user->name = 'Replaced';
}
$a = new stdClass();
$a->name = 'Original';
replaceWithoutReference($a);
echo $a->name . "\n";
$b = new stdClass();
$b->name = 'Original';
replaceWithReference($b);
echo $b->name . "\n";
Output
Original
Replaced
- Without
&, assigning a new object to$useronly changes the function's local copy of the handle; the caller still has the original object. - With
&,$useris the caller's variable, so it now holds the new object.
Performance Myth
It is sometimes assumed that passing large arrays by reference is faster. In modern PHP, this is generally not true:
- PHP uses copy-on-write: passing an array by value does not copy it. A copy is made only if the function modifies the array.
- References can even prevent some internal optimizations.
Use references when you intend to modify the caller's variable — not as a performance trick.
Common Mistakes
Unexpected Side Effects
Effect: A caller's variable changes without any visible assignment at the call site, which makes bugs hard to trace.
Fix: Prefer returning new values; use references only when modifying in place is the clear intent, and name functions accordingly (sortProducts(), addToCart()).
Passing Literals or Function Results
Effect: An Error for user-defined functions, or a "Only variables should be passed by reference" notice for built-ins.
Fix: Store the value in a variable first.
Forgetting the & in the Declaration
Effect: The function silently works on a copy, and the caller's variable is not updated.
Fix: Add & to the parameter, or return the value and assign it.
Leftover References in foreach
Effect: After foreach ($items as &$item), the variable still references the last element and can overwrite it later.
Fix: unset($item); after the loop (see Foreach Loop).
Best Practices
- Default to pass-by-value and return results.
- Use references when a function's purpose is to modify its argument in place (as
sort()does) or when a built-in API requires it. - Make reference usage obvious through function names and documentation.
- Return arrays (with destructuring) instead of using several output parameters.
- Do not use references for performance; copy-on-write already avoids unnecessary copies.
Official reference: https://www.php.net/manual/en/functions.arguments.php#functions.arguments.by-reference