I have seen here several related questions, none of which clearly provide an answer. I am implementing a theme where I want the node content (with its title, the tabs, etc.) themed completely separately (i.e. in a different div) from the comments. The initial problem is that part of what I consider the node content (the title, the tabs) is rendered in page.tpl.php and part (the node body itself) is rendered in node.tpl.php. The problem is that the comments are an integral part of the variable $content in node.tpl.php.

I found part of the solution:

I found the template comment-wrapper.tpl.php. By reimplementing it in my theme, I can cancel the output of the comments (by blanking out the template).

Now, I would like to use mytheme_preprocess_page() to pull up the comments into a variable $comments so that I can add the comments where I want in page.tpl.php.

The remaining problem is how can I get all the variables originally available within comment-wrapper.tpl.php from mytheme_preprocess_page()?

Or do you know another (better) way to achieve the same thing?

Another way to answer the question: who calls comment-wrapper.tpl.php ?

Maybe an answer to that question would help:
$content: reworded about manipulating this variable


A- The node_menu (hook_menu implementation) has node_page_view() as a page callback for a node page.
B- node_page_view() calls node_show() which:
1- is not a themable function. 2- mixes (concatenates) the output of node_view() (the node content itself) and of comment_render().
C- comment_render() calls theme('comment_wrapper', ...)

This is where the serpent bit its tail:
As mentioned in the question, I could reimplement comment-wrapper.tpl.php to nix the output mixed with the node,
but then calling comment_render() separately to get the comments where I want returns nothing for the same reason!

The conclusion is that the solution cannot be implemented by a theme alone. One would need to implement this in a module and override the node_page_view() callback and re-implement node_show(), taking care of the fact that node_show() is also called when viewing a node revision ('node/$nid/revisions/$vid/view').


While hideously ugly, and most probably one of the reasons D7 and beyond have gone to render arrays, you can do something along these lines:

Create a new comment-wrapper.tpl.php in your theme:

<?php if (isset($node->render_comments)): ?>
  <div id="comments">
    <?php print $content; ?>
<?php endif; ?>

Since the "standard" $node object won't/shouldn't include $node->render_comments the various standard drupal core functions dealing with comments won't include the HTML of them.

So, now you can do something like this:

$node=node_load(NID); // if not loaded already

$comments=comment_render($node); // include `$cid` if you need it

with $comments now set to the HTML of the comments on that node.

I would put the above logic in YOURTHEME_preprocess_node() and not in its node.tpl.php template.

But also note, of course/unfortunately, that Drupal is still going to go to all the database effort of rendering the comments both times :(

If this is a performance hit on your system that you want to avoid, you could get even crazier and do something like this in your theme's comment-wrapper.tpl.php:

  <div id="comments">
    <?php print $content; ?>

and then use your implementation of whichever string or regular expression functions you like to cut them out of $content in node.tpl.php itself.

  • Thanks. The performance hit with the double rendering of the comments is not acceptable. I've gone the way described in the accepted answer, overriding the menu callback to bypass the default workflow. – augustin Jan 10 '14 at 3:49

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.