advanced php language
References
References let two variable names point to the same value container. In PHP, references are created with &.
Most application code should avoid references. They make data flow harder to see, and PHP already handles copying efficiently. You need to understand references because they appear in legacy code, certain built-in APIs, and foreach bugs.
Assigning By Reference
Normal assignment copies the value for practical purposes.
<?php
declare(strict_types=1);
$first = 'Ada';
$second = $first;
$second = 'Grace';
echo $first . PHP_EOL;
echo $second . PHP_EOL;
// Prints:
// Ada
// Grace
Reference assignment links the variables.
<?php
declare(strict_types=1);
$first = 'Ada';
$second =& $first;
$second = 'Grace';
echo $first . PHP_EOL;
echo $second . PHP_EOL;
// Prints:
// Grace
// Grace
Changing either variable changes the shared value container.
Passing By Reference
A function parameter can be marked with & so the function can change the caller's variable.
<?php
declare(strict_types=1);
function normaliseEmail(string &$email): void
{
$email = strtolower(trim($email));
}
$email = ' Ada@Example.COM ';
normaliseEmail($email);
echo $email . PHP_EOL;
// Prints:
// ada@example.com
This works, but a return value is usually clearer:
<?php
declare(strict_types=1);
function normalisedEmail(string $email): string
{
return strtolower(trim($email));
}
echo normalisedEmail(' Ada@Example.COM ') . PHP_EOL;
// Prints:
// ada@example.com
Prefer returning a new value unless there is a strong reason to mutate the caller's variable.
foreach By Reference
foreach can iterate by reference, which lets you modify array elements in place.
<?php
declare(strict_types=1);
$names = [' Ada ', ' Grace '];
foreach ($names as &$name) {
$name = trim($name);
}
unset($name);
echo implode(', ', $names) . PHP_EOL;
// Prints:
// Ada, Grace
The unset($name) matters. After a by-reference foreach, the loop variable still references the last element. Forgetting to unset it can cause surprising bugs later.
<?php
declare(strict_types=1);
$numbers = [1, 2, 3];
foreach ($numbers as &$number) {
$number *= 10;
}
unset($number);
foreach ($numbers as $number) {
echo $number . PHP_EOL;
}
// Prints:
// 10
// 20
// 30
If you use by-reference foreach, unset the loop variable immediately afterward.
Objects Are Different
Object variables already hold an object handle. Assigning an object variable to another variable does not clone the object.
<?php
declare(strict_types=1);
final class Counter
{
public int $value = 0;
}
$first = new Counter();
$second = $first;
$second->value++;
echo $first->value . PHP_EOL;
// Prints:
// 1
You do not need & to let two variables refer to the same object. Use clone if you need a different object.
References And Return Values
PHP can return by reference, but this should be rare. It exposes internal storage and makes mutation hard to track.
<?php
declare(strict_types=1);
final class Settings
{
/** @var array<string, string> */
private array $values = ['timezone' => 'UTC'];
public function get(string $key): string
{
return $this->values[$key] ?? '';
}
}
$settings = new Settings();
echo $settings->get('timezone') . PHP_EOL;
// Prints:
// UTC
Returning a value or providing a clear setter is usually better than returning references to internal arrays.
When References Are Useful
References are sometimes used by PHP built-ins, legacy APIs, performance-sensitive internals, and functions that intentionally write output variables.
For application code, consider alternatives first:
- return a transformed value
- return a result object
- mutate an object through a named method
- use a collection method
- use
array_map()or a normal loop that builds a new array
References should make the code simpler, not more mysterious.
What You Should Be Able To Do
After this lesson, you should be able to explain reference assignment, pass-by-reference parameters, by-reference foreach, and why object variables usually do not need &.
For junior work, the most important habit is spotting accidental reference bugs, especially after foreach (&$value).
Practice
Practice: Trim An Array By Reference Safely
Create a small PHP example using foreach by reference.
Task
Build an example that:
- starts with an array of names containing extra spaces
- trims each name in place with
foreach (&$name) - unsets the loop variable afterward
- prints the cleaned names
Use strict types. Keep the expected output in the PHP code block as printed lines or comments.
Check Your Work
Confirm:
- the array values are changed in place
- the loop variable is unset after the reference loop
- a second normal loop works correctly
Afterward, explain why forgetting unset($name) can cause a bug.
Show solution
This solution uses reference iteration deliberately and then breaks the reference with unset().
<?php
declare(strict_types=1);
$names = [' Ada ', ' Grace ', ' Linus '];
foreach ($names as &$name) {
$name = trim($name);
}
unset($name);
foreach ($names as $name) {
echo $name . PHP_EOL;
}
// Prints:
// Ada
// Grace
// Linus
Forgetting unset($name) leaves $name referencing the last array element. A later assignment to $name can accidentally overwrite that last element.