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