WeakMap 类

(PHP 8)

简介

一个 WeakMap 是一个映射(或字典),它接受对象作为键。但是,与其他类似的 SplObjectStorage 不同,WeakMap 中的键对象不会影响该对象的引用计数。也就是说,如果在任何时候对象唯一的剩余引用是 WeakMap 的键,该对象将被垃圾回收并从 WeakMap 中删除。它的主要用例是为从对象派生的数据构建缓存,这些数据不需要比对象存活更长时间。

WeakMap 实现 ArrayAccessTraversable(通过 IteratorAggregate)和 Countable,所以在大多数情况下,它可以像关联数组一样使用。

类概要

final class WeakMap implements ArrayAccess, Countable, IteratorAggregate {
/* 方法 */
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
}

示例

示例 #1 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));

上面的示例将输出

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

目录

添加注释

用户贡献的注释 2 个注释

Samu
8 个月前
PHP 对 WeakMap 的实现允许遍历弱映射的内容,因此了解为什么它有时很危险并且需要仔细考虑非常重要。

如果 WeakMap 的对象由其他服务(如 Doctrine 的 EntityManager)管理,那么永远不要假设如果对象仍然存在于弱映射中,它就仍然受 Doctrine 管理,因此可以安全地使用。

Doctrine 可能已经丢弃了该实体,但某些无关的代码可能仍然持有对它的引用,因此它也仍然存在于映射中。

如果您将受管理的对象放入 WeakMap,然后稍后遍历 WeakMap(例如,在 Doctrine 刷新之后),那么对于每个这样的对象,您必须验证它在对象的来源上下文中是否仍然有效。

例如,将分离的 Doctrine 实体分配给另一个实体的属性会导致有关在层次结构中找到未持久化/未管理的实体的错误。
Anton
4 个月前
请记住,如果 Enum case 被用作 WeakMap 的键,它将永远不会被移除,因为它在底层始终至少有一个引用(不确定为什么,可能是因为枚举基本上是一个常量)。
因此,以下两个 WeakMap 将始终具有键 Enum::Case。但是,您仍然可以手动取消设置它

$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