PHP звільняє об'єкт, коли на нього не лишається посилань. Звичайний кеш, що тримає об'єкти як ключі чи значення, не дає їх звільнити - навіть коли решта програми про них уже забула. У довгоживучих процесах (воркери, Octane) це витік пам'яті.
WeakReference (PHP 7.4) - посилання, яке не заважає збирачу сміття:
$user = new User();
$ref = WeakReference::create($user);
$ref->get(); // об'єкт
unset($user);
$ref->get(); // null - об'єкт уже звільнено
WeakMap (PHP 8.0) - словник, де ключі - об'єкти, утримувані слабко. Коли ключ-об'єкт звільнено, запис зникає з мапи сам:
final class PriceCalculator
{
private WeakMap $cache;
public function __construct()
{
$this->cache = new WeakMap();
}
public function totalFor(Order $order): int
{
return $this->cache[$order] ??= $this->expensiveCalculation($order);
}
}
Кеш живе рівно стільки, скільки живе кожне замовлення, і не росте безмежно.
Де застосовують:
- Мемоізація за об'єктом-аргументом - як у прикладі.
- Метадані до чужих об'єктів, які не можна змінити (сутності ORM, об'єкти бібліотек).
- Реєстри й ідентичні мапи в ORM і контейнерах, що не мають утримувати сутності довше за запит.
Обмеження: ключі WeakMap - лише об'єкти; значення утримуються сильно (якщо значення посилається на ключ, запис не звільниться). Момент звільнення залежить від лічильника посилань і збирача циклів, тож логіку коректності на ньому не будують - лише оптимізації.