Early Bird Registration for DrupalCon Portland 2024 is open! Register by 23:59 UTC on 18 March 2024, to get $100 off your ticket.
By Wim Leers on
Change record status:
Published (View all published change records)
Project:
Introduced in branch:
8.0.x
Introduced in version:
8.0.0-BETA12
Issue links:
Description:
- Added
#lazy_builder
callbacks, which are given only arguments that may contain only primitive types (string, int, bool, float, NULL), not objects. - Added
#create_placeholder
, which allows a render array to be forced to be placeholdered.
In a follow-up issue, automatic placeholdering will be introduced. (Basically: ifmax-age = 0
or high-cardinality cache contexts are present for the subtree, set#create_placeholder
= TRUE.) - Removed
#post_render_cache
(the above is its successor). - Removed
RendererInterface::generateCachePlaceholder()
anddrupal_render_cache_generate_placeholder()
because they are now obsolete.
A new general recommendation
- A
#lazy_builder
can build a render array from scratch. It is given only the arguments that you provide it, and that context may contain only primitive types (string, bool, int, float, NULL).- When specifying
#cache
, provide a#lazy_builder
to build out the entire render array in case of a cache miss.- Together, the two above points allow Drupal to optimize: it is able to determine based on how dynamic the contents of the
#builder
callback are, whether the#lazy_builder
(and thus the associated render array) should be rendered during the initial page load, or via BigPipe or ESI.- Arguments should only be passed from an object that is already provided to a parent element. Otherwise, if the render array is standalone (not a child of any parent element) then the arguments should be retrieved inside the callback itself.
Concrete changes
- Before
-
$callback = 'comment.post_render_cache:renderForm'; $context = array( 'entity_type' => $entity->getEntityTypeId(), 'entity_id' => $entity->id(), 'field_name' => $field_name, 'comment_type' => $this->getFieldSetting('comment_type'), ); $placeholder = drupal_render_cache_generate_placeholder($callback, $context); $output['comment_form'] = array( '#post_render_cache' => array( $callback => array( $context, ), ), '#markup' => $placeholder, );
-
public function renderForm(array $element, array $context) { $values = array( 'entity_type' => $context['entity_type'], 'entity_id' => $context['entity_id'], 'field_name' => $context['field_name'], 'comment_type' => $context['comment_type'], 'pid' => NULL, ); $comment = $this->entityManager->getStorage('comment')->create($values); $form = $this->entityFormBuilder->getForm($comment); $markup = $this->renderer->render($form); $callback = 'comment.post_render_cache:renderForm'; $placeholder = $this->generatePlaceholder($callback, $context); $element['#markup'] = str_replace($placeholder, $markup, $element['#markup']); $element = $this->renderer->mergeBubbleableMetadata($element, $form); return $element; }
- After
-
$output['comment_form'] = [ '#lazy_builder' => ['comment.lazy_builders:renderForm', [ $entity->getEntityTypeId(), $entity->id(), $field_name, $this->getFieldSetting('comment_type'), ]], '#create_placeholder' => TRUE, ];
-
public function renderForm($commented_entity_type_id, $commented_entity_id, $field_name, $comment_type_id) { $values = array( 'entity_type' => $commented_entity_type_id, 'entity_id' => $commented_entity_id, 'field_name' => $field_name, 'comment_type' => $comment_type_id, 'pid' => NULL, ); $comment = $this->entityManager->getStorage('comment')->create($values); return $this->entityFormBuilder->getForm($comment); }
Impacts:
Module developers
Comments
Why do I need to specifically
Why do I need to specifically declare #create_placeholder ?
Also, why can't we provide
Also, why can't we provide whatever value we want but only strings, integers, null...? Can't the the arguments be serialized before rendering and unserialized before passing to the builder? If I have a configuration that has many values, has arrays or unknown structures(arrays) then I am passing it as serialized string. I don't see why this could not be taken care of in the core.
Please read the issue that
Please read the issue that introduced it. Not going to repeat an entire discussion in comments here.
Manual placeholdering vs auto-placeholdering
You don't, see https://www.drupal.org/node/2499157.
#create_placeholder = TRUE
is for manual placeholdering.