I wonder what's the right way to render entity render array as a token replacement (value). I found 3 different ways in the contrib:

Looking at https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Renderer.php/function/Renderer%3A%3ArenderPlain/9.3.x, it looks like this method should be the correct one, given the description:

Useful for instance when rendering the values of tokens or emails, which need a render array being turned into a string

Is that true?

  • Yes, if you need to turn a render array into a string without bubbling up cache metadata to the page (where it doesn't belong because the content goes into an email), then this is true.
    – 4uk4
    Nov 12, 2022 at 11:14
  • Thanks. This is interesting, because I interpreted this as useful for rendering the values of token generally ("or"). Nov 12, 2022 at 12:11

1 Answer 1


No, for example the mentioned AET module is mainly targeted to render entities via the token filter in the body field of other entities. Then the render method is more appropriate to bubble up the metadata and also not to replace placeholders too early. But this not perfect, either.

You find a better example in the core media embed filter, where in a token you would merge with $bubbleable_metadata:


   * Renders the given render array into the given DOM node.
   * @param array $build
   *   The render array to render in isolation.
   * @param \DOMNode $node
   *   The DOM node to render into.
   * @param \Drupal\filter\FilterProcessResult $result
   *   The accumulated result of filter processing, updated with the metadata
   *   bubbled during rendering.
  protected function renderIntoDomNode(array $build, \DOMNode $node, FilterProcessResult &$result) {
    // We need to render the embedded entity:
    // - without replacing placeholders, so that the placeholders are
    //   only replaced at the last possible moment. Hence we cannot use
    //   either renderPlain() or renderRoot(), so we must use render().
    // - without bubbling beyond this filter, because filters must
    //   ensure that the bubbleable metadata for the changes they make
    //   when filtering text makes it onto the FilterProcessResult
    //   object that they return ($result). To prevent that bubbling, we
    //   must wrap the call to render() in a render context.
    $markup = $this->renderer->executeInRenderContext(new RenderContext(), function () use (&$build) {
      return $this->renderer->render($build);
    $result = $result->merge(BubbleableMetadata::createFromRenderArray($build));
    static::replaceNodeContent($node, $markup);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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