PHP Conference Nagoya 2025

A classe WeakMap

(PHP 8)

Introdução

Um WeakMap é um mapa (ou dicionário) que aceita objetos como chaves. Entretanto, diferentemente do objeto similar SplObjectStorage, um objeto em uma chave de um WeakMap não contribui com a contagem de referência do objeto. Isto é, se em algum ponto a única referência restante a um objeto é a chave de um WeakMap, o objeto sofrerá uma coleta de lixo e será removido do WeakMap. Seu caso de uso primário é construir caches de dados derivados de um objeto que não precisam durar mais que o objeto.

WeakMap implementa ArrayAccess, Traversable (via IteratorAggregate) e Countable, por isso na maioria dos casos pode ser usada da mesma forma que um array associativo.

Resumo da classe

final class WeakMap implements ArrayAccess, Countable, IteratorAggregate {
/* Métodos */
public count(): int
public offsetExists(object $object): bool
public offsetGet(object $object): mixed
public offsetSet(object $object, mixed $value): void
public offsetUnset(object $object): void
}

Exemplos

Exemplo #1 Exemplo de uso de Weakmap

<?php
$wm
= new WeakMap();

$o = new stdClass;

class
A {
public function
__destruct() {
echo
"Dead!\n";
}
}

$wm[$o] = new A;

var_dump(count($wm));
echo
"Unsetting...\n";
unset(
$o);
echo
"Done\n";
var_dump(count($wm));

O exemplo acima produzirá:

int(1)
Unsetting...
Dead!
Done
int(0)

Índice

adicione uma nota

Notas Enviadas por Usuários (em inglês) 2 notes

up
9
Samu
1 year ago
PHP's implementation of WeakMap allows for iterating over the contents of the weak map, hence it's important to understand why it is sometimes dangerous and requires careful thought.

If the objects of the WeakMap are "managed" by other services such as Doctrine's EntityManager, it is never safe to assume that if the object still exists in the weak map, it is still managed by Doctrine and therefore safe to consume.

Doctrine might have already thrown that entity away but some unrelated piece of code might still hold a reference to it, hence it still existing in the map as well.

If you are placing managed objects into the WeakMap and later iterating over the WeakMap (e.g. after Doctrine flush), then for each such object you must verify that it is still valid in the context of the source of the object.

For example assigning a detached Doctrine entity to another entity's property would result in errors about non-persisted / non-managed entities being found in the hierarchy.
up
1
Anton
8 months ago
Keep in mind that if Enum case is put as a key to WeakMap, it will never be removed because it will always have unless 1 reference to it under the hood (not sure why, probably because enum is basically a constant).
Therefore, both WeakMaps below will always have key Enum::Case. However, you still are able to unset it manually:

$weakMap = new WeakMap();
$object = Enum::Case;

$weakMap[$object] = 123;
unset($object);
var_dump($weakMap->count()); // 1

///

$weakMap = new WeakMap();
$weakMap[Enum::Case] = 123;
var_dump($weakMap->count()); // 1

///

$weakMap = new WeakMap();
$weakMap[Enum::Case] = 123;
unset($weakMap[Enum::Case]);
var_dump($weakMap->count()); // 0
To Top