skip to content

In PHP, what does WeakReference::create() return, and what does its get() method give back once the object is destroyed?

level: middleimportance: nice to knowfreq 12%

answer

  1. does not raise the refcount
  2. get() returns ?object
  3. null once the object is gone
  4. same WeakReference for the same object
  5. final, not serializable, no new

basics

~20 s

WeakReference::create($obj) returns a WeakReference that points at the object without increasing its refcount. While the object lives, get() returns it; once the last normal reference is gone and the object is destroyed, get() returns null.

solid answer

~40 s

`WeakReference::create(object $object): WeakReference` gives you a handle that does **not** keep the object alive: PHP destroys the object when its ordinary refcount reaches zero, exactly as if the weak reference did not exist. Afterwards `get(): ?object` returns `null`, so every use must check for it. Calling `create()` again for the same live object returns the **same** `WeakReference` instance. The class is `final`, cannot be built with `new` (that throws an `Error` telling you to use `create()`), cannot be cloned and cannot be serialized. Typical uses are back-pointers and registries that must not extend an object's lifetime — a child that refers to its owner, or a list of subscribers that should vanish when they do. For attaching data to many objects, `WeakMap` is the better tool; `WeakReference` is for holding one object loosely.

code

php · 20 lines
php
<?php
declare(strict_types=1);

final class Node
{
    /** @var list<Node> */
    public array $children = [];
    private ?WeakReference $parent = null;

    public function add(Node $child): void
    {
        $child->parent = WeakReference::create($this);
        $this->children[] = $child;
    }

    public function parent(): ?Node
    {
        return $this->parent?->get();
    }
}

go deeper

for a junior

Know that WeakReference::create() refers to an object without keeping it alive, and that get() returns null once the object is gone.

for a middle

Explain the refcount mechanics, the one-instance-per-object rule, and the restrictions: final, no new, no clone, no serialization.

for a senior

Use weak back-pointers to avoid cycles in long-running code, and catch reviews where get() results are stored and silently become strong references.

for a principal

Decide where object lifetimes should be explicit ownership versus weak observation, so long-running services do not accumulate objects nobody owns.

## What it is A normal PHP variable that holds an object increases the object's **refcount**, and the object is destroyed only when that count reaches zero. `WeakReference` is a small `final` class whose instances point at an object **without** counting as a reference. The object's lifetime is decided solely by its ordinary references. ```php $ticket = new Ticket(42); $ref = WeakReference::create($ticket); var_dump($ref->get() === $ticket); // bool(true) unset($ticket); // last normal reference gone var_dump($ref->get()); // NULL ``` ## The API | Member | Behaviour | |---|---| | `WeakReference::create(object $object): WeakReference` | returns a weak reference to the object | | `get(): ?object` | the object while it exists, `null` after it has been destroyed | | `new WeakReference()` | throws `Error`: direct instantiation is not allowed | | `clone $ref` | throws `Error`: the class cannot be cloned | | `serialize($ref)` | throws: weak references cannot be serialized | Two details are easy to miss: - **One instance per object.** While the object lives, `create()` returns the same `WeakReference` each time, so `WeakReference::create($a) === WeakReference::create($a)` is `true`. - **`get()` re-strengthens.** The value `get()` returns is an ordinary reference. If you store it in a property, you are back to keeping the object alive. Use it locally and let it go. ## When the object disappears The object is destroyed when its refcount reaches zero — typically at the `unset()` or reassignment of its last variable, or when the function holding it returns. If the object is part of a reference cycle, it disappears only when the cycle collector frees that cycle, so `get()` can keep returning it for a while after your code stopped using it. Its destructor runs at destruction, before `get()` starts returning `null`. ## Where it fits in PHP code 1. **Back-pointers.** A child object that needs to reach its parent can hold `WeakReference::create($parent)` instead of `$parent` itself, which avoids creating a cycle and lets refcounting free the whole structure promptly. 2. **Registries of live objects.** A list of open connections or subscribers held as weak references does not keep them alive; entries whose `get()` returns `null` are pruned on the next pass. 3. **Memoisation keyed by one object.** For one long-lived object, a weak reference avoids pinning it. For mapping **many** objects to data, a `WeakMap` is simpler: it removes entries automatically when their key object dies, where a list of `WeakReference`s needs manual pruning. ## What it does not do - It does not make PHP's memory behaviour lazy or pressure-based: there is no "clear when memory is low" variant. A weakly referenced object is destroyed as soon as its ordinary refcount hits zero, whatever the memory situation. - It does not survive the request in a web context: like everything else, it is gone when the request ends. - It is not serializable, so it cannot be put into a session or a cache as-is. ## Choosing between the three kinds of link | Link | Keeps the object alive | Removes itself when the object dies | Typical use | |---|---|---|---| | ordinary variable or property | yes | no | ownership | | `WeakReference` | no | no, `get()` returns `null` | one loose pointer, such as a parent link | | `WeakMap` entry keyed by the object | no | yes | data attached to many objects | Ownership should be explicit: exactly one part of the program owns an object through ordinary references, and everything that merely observes it uses a weak link. ## Pitfalls in review - Calling `$ref->get()->method()` without a `null` check fails with an `Error` as soon as the object has gone. - Storing the result of `get()` in a long-lived property silently turns the weak link into a strong one. - Expecting `get()` to return `null` right after `unset()` when the object is still referenced elsewhere, or is part of an uncollected cycle.

  • Why does storing $ref->get() in a property defeat the purpose of the weak reference?
    `get()` returns an ordinary object reference. Keeping it in a property increments the object's refcount like any other variable, so the object can no longer be destroyed while that property holds it. Call `get()` where you need the object and let the result go out of scope.
  • When would you use WeakMap instead of WeakReference?
    When you need to associate data with many objects. A `WeakMap` keyed by objects removes each entry automatically when its key object is destroyed; a collection of `WeakReference`s leaves dead entries behind that you must prune yourself.

saying these in an interview costs you the question

  • A WeakReference keeps its object alive until get() is called
  • new WeakReference($obj) is how you create one
  • get() throws an exception once the object is destroyed
  • PHP clears weakly referenced objects only under memory pressure
  • WeakReference objects can be serialized into a session