advanced php language

Weak References

A weak reference lets code refer to an object without keeping that object alive. If the rest of the program stops strongly referencing the object, PHP can garbage-collect it and the weak reference will return null.

Weak references are specialist tooling. You may see them in caches, object metadata stores, event systems, proxy libraries, containers, and framework internals. Most business code should use normal object references.

Strong References Keep Objects Alive

A normal object variable keeps the object alive.

PHP example
<?php

declare(strict_types=1);

final class User
{
    public function __construct(
        public string $email,
    ) {
    }
}

$user = new User('ada@example.com');
$anotherReference = $user;

unset($user);

echo $anotherReference->email . PHP_EOL;

// Prints:
// ada@example.com

The object still exists because $anotherReference points to it.

WeakReference

WeakReference::create() creates a weak reference to an object. Calling get() returns the object while it is still alive, or null after it has been collected.

PHP example
<?php

declare(strict_types=1);

final class User
{
    public function __construct(
        public string $email,
    ) {
    }
}

$user = new User('ada@example.com');
$weak = WeakReference::create($user);

echo $weak->get()?->email . PHP_EOL;

unset($user);
gc_collect_cycles();

echo $weak->get() === null ? 'collected' : 'still alive';
echo PHP_EOL;

// Prints:
// ada@example.com
// collected

The weak reference did not keep the user object alive.

WeakMap

WeakMap stores values against object keys without keeping those object keys alive. When the object key is collected, the entry disappears.

PHP example
<?php

declare(strict_types=1);

final class Request
{
}

$metadata = new WeakMap();
$request = new Request();

$metadata[$request] = ['started_at' => '10:00'];

echo count($metadata) . PHP_EOL;

unset($request);
gc_collect_cycles();

echo count($metadata) . PHP_EOL;

// Prints:
// 1
// 0

This is useful for attaching metadata to objects without modifying their classes and without leaking memory in long-running processes.

Why This Matters In Long-Running PHP

Traditional PHP request/response applications often exit after each request, so memory is released quickly. Long-running workers are different: queue workers, WebSocket servers, async runtimes, daemons, and test processes can stay alive for a long time.

If a long-running process stores normal references in a global cache or static array, objects may never be collected. Weak references can help avoid that in library-level code.

When Not To Use Weak References

Do not use weak references to avoid deciding ownership. If an object is needed for a business operation, use a normal reference and make the lifetime clear.

Weak references can make code harder to reason about because get() may return an object now and null later. That is useful for caches and metadata, but awkward for ordinary application logic.

What You Should Be Able To Do

After this lesson, you should be able to explain that weak references do not keep objects alive, use WeakReference::create(), recognise WeakMap, and understand why this is mainly useful in caches, metadata stores, and long-running processes.

For junior work, the practical skill is recognising weak references in framework or library code without mistaking them for normal ownership.

Practice

Practice: Observe A Weak Reference

Create a small PHP example that shows a weak reference becoming empty.

Task

Build:

  • a simple object
  • a WeakReference to that object
  • output while the object is still strongly referenced
  • output after unsetting the strong reference and collecting cycles

Use strict types. Keep the expected output in the PHP code block as printed lines or comments.

Check Your Work

Confirm:

  • get() returns the object before it is unset
  • the weak reference does not keep the object alive
  • get() returns null after collection

Afterward, explain why this is useful for cache-like library code but uncommon in normal business logic.

Show solution

This solution shows that the weak reference can see the object while it exists but does not keep it alive.

PHP example
<?php

declare(strict_types=1);

final class User
{
    public function __construct(
        public string $email,
    ) {
    }
}

$user = new User('ada@example.com');
$weak = WeakReference::create($user);

echo $weak->get()?->email . PHP_EOL;

unset($user);
gc_collect_cycles();

echo $weak->get() === null ? 'collected' : 'still alive';
echo PHP_EOL;

// Prints:
// ada@example.com
// collected

This is useful for cache-like library code because metadata or cached values can disappear when the original object disappears. Normal business logic usually needs clear ownership, so a normal reference is easier to reason about.