Score:1

User-specific caching, but not necessarily the current user

nl flag

Background

I'm creating a render array that is built for a specific user, from data related to that user. The resulting render array is dependent on the user ID that is passed in, and it will be rendered in a block.

The resulting block will be built and shown to the user whose data it is. However, it could also be shown to privileged users via another page, where they select a user from an Entity Autocomplete dropdown and click "view" to view that user's data result.

Problem: How to Cache It

I'm having some trouble understanding the proper usage of cache tags and cache context for my use-case. My current understanding is that the cache tags should be set for the data sources the result is built from, so that if one changes, the cache is invalidated. Say the result shows that a webform has been submitted by the user, so the built data should have the cache tag ['webform_submission_list:WEBFORM_ID'].

I don't know, though, if the cache should have user as a cache context, or as a cache tag. The data is certainly specific to a single user, but it's not necessarily the current user. The information I viewed about cache contexts seems to indicate to me that the user context means that the data varies based on the current user, not just a specified user.

Is that right, and if so, would the best way to cache it be to create the render array and then use something like this, not using a cache context?

// Cache ID contains the user's ID.
$cid = "my_module:data:$uid";

// Return if cached.
if ($cache = $this->cacheBackend->get($cid)) {
  return $cache->data;
}

// Build the data, cache it, and return.
$data = $this->build($uid);
$this->cacheBackend->set($cid, $data, time() + $data->getCacheMaxAge(), $data->getCacheTags());
return $data;
4uk4 avatar
cn flag
For the current user both, cache context and cache tag, for other users only cache tags. You can build these things with Views also, contextual filter for the current user, and exposed filter for other users. BTW you don't need low level cache backend code, you can add cache keys to the render array.
mbomb007 avatar
nl flag
@4uk4 If I add the keys to the render array, does that prevent it from calling `$this->build($uid)` again once it's cached? It's an expensive operation.
4uk4 avatar
cn flag
Depending on where the expensive operation takes place, you can add a #pre_render callback. See https://drupal.stackexchange.com/questions/241441/dynamic-page-cache-not-working-for-my-controller
mbomb007 avatar
nl flag
I didn't know that different children in a render array could have different cache keys. That's helpful to know.
mbomb007 avatar
nl flag
When I use a `#pre_render` callback, my implementation of `template_preprocess_HOOK()` for the data is now preprocessing an array that just lists the callback function, rather than the built render array.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.