4

I'm using PHP handlebars templates and would like to keep all of the HTML in the template file so I don't have a header.php but rather the handlebars looks like

<html>
  <head>
    {{#wpHead}}
  </head>

where wpHead is a helper that has nothing but wp_head(); but the output comes first before the <html> tag. I'm thinking I'll have to use output buffering to store it as a string... Is that the only/best way?

The plan with the string is to add it to the data array that is passed to the handlebars render function:

global $post;
$data = array(
    'wpHead' => get_wp_head_as_string(),
    'postContent' => $post->post_content,
    'postContentFiltered' => apply_filters( 'the_content', $post->post_content )
);
render( 'default', $data );

And then just output it directly in the template instead of with a helper:

<html>
<head>
    <!-- other head stuff -->
    {{{wpHead}}} <!-- wp head output -->
</head>
<body>
    {{{postContentFiltered}}}
</body>

3
  • 1
    You'll need the footer too, which leads to a new problem of event ordering, your entire action/hook life cycle will happen all at once, which could cause compatibility issues. You would be better to keep the header separate else you could run into obscure and difficult to debug issues with certain plugins
    – Tom J Nowell
    Jan 9, 2017 at 17:44
  • @TomJNowell interesting - i can see how that might occur. I'm using output buffering for now - will test it out and see how it goes, it structured so I can easily swap out the wphead and wpfooter back to the PHP calls, if need be.
    – tsdexter
    Jan 9, 2017 at 19:45
  • 2
    output buffers is probably the only way to do that, wp_head isn't intended to return a string
    – Tom J Nowell
    Jan 9, 2017 at 19:47

2 Answers 2

2

You can use PHP's output buffering. WIth this you can write a wrapper for the get_head() function

function wpse251841_wp_head() {
    ob_start();
    wp_head();
    return ob_get_clean();
}

You can then use this as

$data = array(
    'wpHead' => wpse251841_wp_head(),
    'postContent' => $post->post_content,
    'postContentFiltered' => apply_filters( 'the_content', $post->post_content )
);

Reference: Output Control Functions

1
  • 2
    Incredible thank you, this solution has served me a lot.! Aug 12, 2019 at 16:47
0

Thanks to @Tunji's answer, I accomplished this with a more generic function:

  /**
  * Use output buffering to convert a function that echoes
  * to a return string instead
  */
  function echo_to_string( $function )
  {
    ob_start();
    call_user_func( $function );
    $html = ob_get_contents();
    ob_end_clean();
    return $html;
  }

Then it can be used like this:

$data->wpHead = echo_to_string( 'wp_head' );

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.