Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як кешувати обчислювані властивості між запитами і як не показати користувачу чужі дані?

Звичайна обчислювана властивість кешується лише в межах одного запиту. Для дорогих даних є кешування довше - через кеш Laravel.

persist: true - кеш для цього екземпляра компонента між його запитами (типово 3600 секунд):

#[Computed(persist: true, seconds: 600)]
public function stats()
{
    return Order::query()->where('shop_id', $this->shopId)->selectRaw('...')->first();
}

Користувач клацає фільтри, а важка статистика не перераховується на кожен клік.

cache: true - кеш спільний для всіх екземплярів компонента в застосунку:

#[Computed(cache: true, key: 'homepage-popular-posts', seconds: 300)]
public function popularPosts()
{
    return Post::popular()->limit(10)->get();
}

Одна й та сама головна сторінка для всіх - запит раз на п'ять хвилин замість кожного рендеру.

Головний ризик - cache: true з персональними даними:

#[Computed(cache: true)]   // помилка!
public function myOrders()
{
    return auth()->user()->orders()->latest()->get();
}

Ключ кешу не залежить від користувача. Перший, хто відкрив сторінку, «заповнить» кеш своїми замовленнями, а наступні побачать його дані. Це витік персональних даних, а не просто баг.

Правила:

  • cache: true - лише для даних, однакових для всіх (публічні списки, довідники, загальна статистика);
  • якщо дані залежать від користувача, мови, параметрів - ключ має їх містити (key: "orders-user-{$id}" неможливо в атрибуті, тож для таких випадків - звичайний Cache::remember у методі з явним ключем) або використовувати persist: true, прив'язаний до екземпляра;
  • інвалідація: кеш живе до закінчення терміну. Після зміни даних unset($this->stats) скидає лише кеш у межах запиту; для збережених значень потрібне явне очищення через кеш Laravel чи коротший термін;
  • серіалізація: у кеш потрапляють моделі й колекції - перевірте, що драйвер кешу й налаштування serializable_classes дозволяють такі об'єкти;
  • авторизація до кешу: перевірка прав має відбуватися до звернення до кешованого значення, а не всередині методу, який при влучанні в кеш не виконується.

Коли краще не використовувати ці опції: якщо запит швидкий (кілька мілісекунд) - звернення до кешу через мережу (Redis) може коштувати стільки ж, а складність і ризик застарілих даних додаються.

Докладніше в документації: Атрибут Computed

Схожі питання