PHP
#php#php-8-5#bitrix#nodiscard#cache#key#attribute

PHP 8.5: атрибут NoDiscard для ключа кеша (Bitrix)

Функция формирования ключа кеша с #[…oDiscard] (PHP 8.5): предупреждение, если возвращаемое значение не использовано. Приведение (void) для явного игнорирования.

Как использовать

  1. Добавьте #[…oDiscard] перед объявлением функции, возвращающей ключ кеша (или другой важный результат).
  2. Если результат вызова не используется и не отброшен явно через (void), PHP выдаст предупреждение.
  3. Для намеренного игнорирования вызывайте: (void) buildCacheKey(...); PHP 8.5+.

Функция формирует ключ кеша или ID, но вызывающий код иногда забывает подставить результат в get/set — кеш работает не с тем ключом или не срабатывает. Ошибка проявляется не сразу. В PHP 8.5 добавлен атрибут NoDiscard: если возвращаемое значение функции не использовано и не отброшено явно через (void), выдаётся предупреждение. Проблема: вызов buildCacheKey() без присвоения в переменную — ключ теряется, кеш по неверному ключу. Симптомы: кеш «не держит» данные, дублирование запросов. Ниже — функция ключа кеша с #[\NoDiscard], пример использования в Bitrix Cache и подавление предупреждения через (void); проверка и типичные ошибки.

Решение

Атрибут #[\NoDiscard] заставляет учитывать возвращаемое значение: не использовано и не отброшено через (void) — предупреждение. Удобно для функций, формирующих ключ кеша, ID или URL.

<?php

#[\NoDiscard]
function buildCacheKey(string $module, string $entity, string $id): string
{
    return $module . ':' . $entity . ':' . $id;
}

// Предупреждение: return value should be used or (void)
buildCacheKey('sale', 'order', '123');

// Корректно: результат используется
$key = buildCacheKey('sale', 'order', '123');
$cache->get($key);

// Корректно: намеренное игнорирование
(void) buildCacheKey('sale', 'order', '123');

Использование с Bitrix Cache:

use Bitrix\Main\Data\Cache;

$cache = Cache::createInstance();
$key = buildCacheKey('sale', 'order', (string) $orderId);
if ($cache->initCache(3600, $key, '/sale/order/')) {
    $data = $cache->getVars();
} elseif ($cache->startDataCache()) {
    // ...
    $cache->endDataCache($data);
}

По документации PHP 8.5: атрибут в глобальном пространстве — #[\NoDiscard]. Приведение (void) не меняет выполнение, но подавляет предупреждение и явно показывает намерение не использовать значение.

Проверка

  1. Предупреждение при неиспользовании результата — вызовите функцию без присвоения и без (void):
#[\NoDiscard]
function buildCacheKey(string $module, string $entity, string $id): string
{
    return $module . ':' . $entity . ':' . $id;
}
buildCacheKey('sale', 'order', '123');

Запуск с отображением предупреждений (например php -d error_reporting=E_ALL script.php) должен выдать предупреждение о том, что возвращаемое значение должно быть использовано или отброшено через (void).

  1. Использование результата — при присвоении в переменную или передаче в другой вызов предупреждения не должно быть.

  2. Явное игнорирование — строка (void) buildCacheKey(...); не должна вызывать предупреждение. Подходит для случаев, когда ключ нужен только для сброса по тегу или побочного эффекта.

  3. PHP 8.5 — атрибут NoDiscard появился в 8.5. На старых версиях атрибут может игнорироваться. Проверьте: php -v.

Типичные ошибки

  • Игнорирование предупреждения — если результат действительно не нужен (например только сброс кеша по тегу), явно пишите (void) buildCacheKey(...);. Иначе при включённых предупреждениях лог засоряется или CI падает.
  • Функция возвращает void — #[\NoDiscard] имеет смысл только у функций, возвращающих значение. У void-функций возвращаемого значения нет, атрибут не нужен.
  • Путаница с (void) — (void) не выполняет функцию заново и не меняет поведение; это только приведение типа результата для подавления предупреждения NoDiscard.

Где применять

  • Bitrix: ключи кеша по модулю/сущности/ID, теги, любые функции, чей результат обязан быть передан в initCache/startDataCache или другой API.
  • Любой PHP 8.5+: генерация ID, URL, токенов — везде, где забытый результат ведёт к трудноотлаживаемой ошибке.

Связанные сниппеты: Option::get с union type, Идемпотентный агент с блокировкой, Cron/Agent: lock-файл.