- Issue created by @kristiaanvandeneynde
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
π€ Interesting. It's been too long for me to remember the details on this, but two immediate thoughts:
- something can only be cached individually if and only if it has
#cache[keys]
set:
// Try to fetch the prerendered element from cache, replace any placeholders // and return the final markup. if (isset($elements['#cache']['keys'])) {
- β¦ which I guess maybe (I do not recall!) implies that auto-placeholdering is impossible? But the detailed validation logic to ensure a reasonable DX does not check for that:
// First validate the usage of #lazy_builder; both of the next if-statements // use it if available. if (isset($elements['#lazy_builder'])) { assert(is_array($elements['#lazy_builder']), 'The #lazy_builder property must have an array as a value.'); assert(count($elements['#lazy_builder']) === 2, 'The #lazy_builder property must have an array as a value, containing two values: the callback, and the arguments for the callback.'); assert(is_array($elements['#lazy_builder'][1]), 'The #lazy_builder argument for callback must have an array as a value.'); assert(count($elements['#lazy_builder'][1]) === count(array_filter($elements['#lazy_builder'][1], function ($v) { return is_null($v) || is_scalar($v); })), "A #lazy_builder callback's context may only contain scalar values or NULL."); assert(!Element::children($elements), sprintf('When a #lazy_builder callback is specified, no children can exist; all children must be generated by the #lazy_builder callback. You specified the following children: %s.', implode(', ', Element::children($elements)))); $supported_keys = [ '#lazy_builder', '#cache', '#create_placeholder', '#lazy_builder_preview', '#preview', // The keys below are not actually supported, but these are added // automatically by the Renderer. Adding them as though they are // supported allows us to avoid throwing an exception 100% of the time. '#weight', '#printed', ]; assert(empty(array_diff(array_keys($elements), $supported_keys)), sprintf('When a #lazy_builder callback is specified, no properties can exist; all properties must be generated by the #lazy_builder callback. You specified the following properties: %s.', implode(', ', array_diff(array_keys($elements), $supported_keys)))); } // Determine whether to do auto-placeholdering. if ($this->placeholderGenerator->canCreatePlaceholder($elements) && $this->placeholderGenerator->shouldAutomaticallyPlaceholder($elements)) { $elements['#create_placeholder'] = TRUE; }
There's no way to do the bubbling of contexts and update the cache redirect if there isn't any containing cacheable parent. I bet that that is the reason?
So AFAICT you're right, and this is a bug. At minimum this is poor DX.
- something can only be cached individually if and only if it has
- π§πͺBelgium kristiaanvandeneynde Antwerp, Belgium
Yeah, in a nutshell: Late placeholdering (i.e. lazy builder added a highly variable cache context) happens in the cache, but if the thing that specified the lazy builder has no cache keys, then the late placeholdering can never take place because it never gets to the cache.