> > The answer is: it depends. If you don’t need the array to clean up after > itself, you can indeed use an array of WeakReference to get most of the way > there. If you want it to clean up after an object gets removed, you either > need to add support to the stored object’s destructor (which isn’t always > possible for built-in or final types), or create your own garbage collector > that scans the array. >
It is indeed doable in userland using WeakReferences, with a small performance penalty: ``` class ReverseWeakMap implements Countable, IteratorAggregate, ArrayAccess { /** * @var array<int|string, WeakReference> */ private array $map = []; public function count(): int { foreach ($this->map as $value => $weakReference) { if ($weakReference->get() === null) { unset($this->map[$value]); } } return count($this->map); } public function getIterator(): Generator { foreach ($this->map as $value => $weakReference) { $object = $weakReference->get(); if ($object === null) { unset($this->map[$value]); } else { yield $value => $object; } } } public function offsetExists(mixed $offset) { if (isset($this->map[$offset])) { $object = $this->map[$offset]->get(); if ($object !== null) { return true; } unset($this->map[$offset]); } return false; } public function offsetGet(mixed $offset): object { if (isset($this->map[$offset])) { $object = $this->map[$offset]->get(); if ($object !== null) { return $object; } unset($this->map[$offset]); } throw new Exception('Undefined offset'); } public function offsetSet(mixed $offset, mixed $value): void { $this->map[$offset] = WeakReference::create($value); } public function offsetUnset(mixed $offset): void { unset($this->map[$offset]); } } ``` Now that I think about it, it might be simpler to add an “onRemove()” > method that takes a callback for the WeakReference class. > > — Rob > A callback when an object goes out of scope would be a great addition to both WeakReference & WeakMap indeed, it would allow custom userland weak maps like the above, with next to no performance penalty! - Benjamin