0

I'm attempting to bypass drupal's internal page cache and dynamic cache when a given url parameter is in a URL (as an anonymous user). The page in question is a view, and occasionally, when a user clicks a link to load that view, the URL has the associated query param. I've tried a number of different ways to add the cache context like below:

$vars['#cache']['contexts'][] = 'url.query_args:dynamic_trials';

I've added this in a hook_preprocess_node, I've added it in a preprocess on the view itself I've added it in a function tibco_views_utils_views_pre_view with a call to

view->element['#cache']['contexts'][] = 'url.query_args:dynamic_trials';

None of these have worked. I noticed this on one of the drupal docs pages:

Note the Internal Page Cache assumes that all pages served to anonymous users will be identical, regardless of the implementation of cache contexts. If you want to use cache contexts to vary the content served to anonymous users, this module must be disabled, and the performance impact that entails incurred

Is this true? There's no way to do what I'm trying to do above without disabling the internal page cache entirely?

3
  • Note that \Drupal::service('page_cache_kill_switch')->trigger(); in a post_execute on the view makes what I want work. I was hoping there was something that absolute than that that worked with query parameters only – plambre May 5 '20 at 21:43
  • It's unclear why you would need to trigger the page cache kill switch.The Internal Page Cache uses as cache ID the entire URL including query string. The Dynamic Page Cache uses cache contexts a View with contextual filter normally bubbles up. – 4k4 May 5 '20 at 21:53
  • The 'dynamic' part of the view occurs in a post_execute. I loop over the $view->result and change the weighting of the results. This works after a cache flush then becomes static on any subsequent refreshes (like the docs quote i pasted). There aren't any contextual filters I don't think. – plambre May 5 '20 at 22:06
1

The Internal Page Cache is designed to serve database content requested by a URL (the entire URL including query string). It works as long as you don't have any dynamic component, for example time based, or client request data not included in URL or session cookie, like request headers or custom cookies.

The Dynamic Page cache works on a different level. It doesn't depend on the URL directly but on the matched route. Any code using contextual data from the request or the matched route has to declare these dependencies as cache metadata.

Your problem is custom code in a Views hook. The old style Views hooks have a very narrow scope while at the same time you can access the entire View. So not all code snippets you find are good practice. Better use the Views plugin system for custom code.

For the caching part the easiest way would be to use the code of the Views caching plugins already in core which you control through the advanced settings of the View. If you only have anonymous traffic already cached by the Internal Page Cache you could disable caching of the View without impacting performance. Either through the none caching plugin or the time-based plugin which gives you finer control.

2
  • I re-implemented this dynamic sorting as a custom views sorting plugin. I then set caching to 'none' in the view UI. After a single load of the view post-cache-flush, the results get set in stone and no longer sort dynamically. Setting caching to none does not change this: X-Drupal-Cache: HIT There must be some further way to bypass the internal page cache – plambre May 12 '20 at 17:55
  • Query parameters are bypassing the Internal Page Cache by default, as explained in the answer. And yes, you get a cache hit when requesting the URL with the same query parameters again. – 4k4 May 12 '20 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.