The Render API overview contains an example for how to use placeholders:

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21...

However, I think this example is incorrect on two counts:

1. '#markup' is an array of a single string, rather than just a single string.
2. 'placeholders' is an array of strings, rather than an array of renderable arrays.

It's difficult to devise a straightforward test to be sure that this is a mistake rather than something misinterpreted, but I've been running at the command line:

drush php-eval '$renderable = ["#markup" => ... ]; print \Drupal::service("renderer")->renderRoot($renderable);'

Respectively, the above two points raise the following two warnings:

1. "strlen() expects parameter 1 to be string, array given Unicode.php:686"; printed string is "Array"
2. "Illegal string offset '#create_placeholder' Renderer.php:163" and "Illegal string offset '#cache' Renderer.php:256"; then fatal error "Cannot use string offset as an array in /var/www/web/core/lib/Drupal/Core/Render/Renderer.php on line 256"

The following markup, on the other hand, works fine and generates the expected string "quux":

$renderable = [
  "#markup" => "@foo",
  "#attached" => [
    "placeholders" => [
      "@foo" => ["#markup" => "quux"],
    ]
  ]
];

Marking this as priority:major as either way it's quite misleading to have this in the worked examples documentation.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jp.stacey created an issue. See original summary.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kunalkursija’s picture

@jp.stacey Agree with you on:

  1. Markup: It should not be an array of strings. When we do that then there are fatal errors with various warnings.
  2. Placeholders: Yes the placeholder values should be renderable arrays which can contain not only markups but other Renderable elements as well

I tried what is mentioned in the documentation for the placeholder as well as what @jp.stacey has given as an example, Where the later worked without any errors.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mlncn’s picture

Yes the incorrect documentation has been ruining what should have been a triumphant first release of this module to frustrating debugging, dead-end searching, and finally finding this issue. Thank you jp.stacey!

So making the placeholders strings, as alleged to be allowed, simply brings disaster.

Something like this:

       $inotherwords[$sequence_id] = [
          $last_element = "First word";
          $first_element = "last word";  
          $connecting_word_markup = "middle word";
          '#markup' => "@first_element @connecting_word @last_element", 
          '#attached' => [
            'placeholders' => [
              '@first_element' => $first_element,
              '@connecting_word' => $connecting_word_markup,
              '@last_element' => $last_element,
            ],
          ],
        ];

Results in:

Warning: Illegal string offset '#create_placeholder' in Drupal\Core\Render\Renderer->renderPlaceholder() 
Warning: Cannot assign an empty string to a string offset in Drupal\Core\Render\Renderer->renderPlaceholder()
Warning: Illegal string offset '#cache' in Drupal\Core\Render\Renderer->doRender() 
Error: Cannot use string offset as an array in Drupal\Core\Render\Renderer->doRender() (line 256 of /var/www/drupal/web/core/lib/Drupal/Core/Render/Renderer.php) 

(minus an extra hundred lines of backtrace)

Whereas ensuring that each string is a render array:

       $last_element = ['#markup' => "First word"];
        $first_element = ['#markup' => "last word"];
        $connecting_word_markup = ['#markup' => "middle word"];
        $inotherwords[$sequence_id] = [
          '#markup' => "@first_element @connecting_word @last_element", 
          '#attached' => [
            'placeholders' => [
              '@first_element' => $first_element,
              '@connecting_word' => $connecting_word_markup,
              '@last_element' => $last_element,
            ],
          ],
        ];

works.

mlncn’s picture

Status: Active » Needs review
FileSize
962 bytes

Here's a patch.

Can we backport critical documentation fixes like this to at least 8.2, since for whatever reason that is what the documentation search defaults to?

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

capysara’s picture

The patch in #8 still applies cleanly to 8.9.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

JamesOakley’s picture

Status: Needs review » Reviewed & tested by the community

Just found this issue having been struggling with why I couldn't get the example to work at https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api....

Thanks

alexpott’s picture

Title: Render API overview example of placeholders either incorrect or misleading » [backport] Render API overview example of placeholders either incorrect or misleading

Committed 323a808 and pushed to 9.1.x. Thanks!

Will backport once the 9.0.x and 8.9.x branches are open again.

  • alexpott committed 323a808 on 9.1.x
    Issue #2848367 by mlncn, jp.stacey, kunalkursija: Render API overview...

  • alexpott committed 0d276f2 on 9.0.x
    Issue #2848367 by mlncn, jp.stacey, kunalkursija: Render API overview...

  • alexpott committed a79aaf6 on 8.9.x
    Issue #2848367 by mlncn, jp.stacey, kunalkursija: Render API overview...
alexpott’s picture

Title: [backport] Render API overview example of placeholders either incorrect or misleading » Render API overview example of placeholders either incorrect or misleading
Status: Reviewed & tested by the community » Fixed

Backported to 8.9.x and 9.0.x

alexpott’s picture

Version: 9.1.x-dev » 8.9.x-dev

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.