Community & Support

Setting $content to $node->content['body']['#value'] in template.php

Our site uses CCK fields for node-specific sidebar content, so in our page.tpl.php file

<?php
 
print $content;
?>

is replaced with
<?php
 
print $node->content['body']['#value'];
?>

for the main content, and the sidebar regions have their respective field's content printed in them.

When loading an admin page, nothing renders, so a page-admin.tpl.php file with

<?php
 
print $content;
?>

was created. When I saw this, I deleted the page-admin.tpl.php file and changed page.tpl.php to use
<?php
 
if(arg(0)=='node'): print $node->content['body']['#value'];                   
    else: print
$content;
  endif;
?>

instead. Right now, with only a couple of page-*.tpl.php files, this is fine, but we expect the number to grow and would like to move this into a function in template.php.

The following snippet is as far as I got, rendering only the word "Array"

<?php
 
function mytheme_preprocess_page(&$vars, $hook) {
    if(
$hook=='page'){
     
$vars['content'] = drupal_set_content($vars['node->content']['body']['#value']);
    }
  }
?>

I'm clearly missing something and/or approaching this totally wrong. Any help will be greatly appreciated. Thank you.

Comments

Preprocess FTW!

This is a pretty hard-cody way of going about this. You may have better results by adjusting the output from the node. However, preprocess functions are definitely the way to go.

Here's what would work using the method you're pursuing:

<?php
 
function mytheme_preprocess_page(&$vars, $hook) {
    if (
$hook == 'page' && arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
     
$vars['content'] = $vars['node->content']['body']['#view'];
    }
  }
?>

This will overwrite the $content variable in the template with the node body only when we're in the context of a node, and not when editing the node. You may also want to add some logic to only do this for certain node types, as this will eliminate a lot of functionality (e.g. comments will never show up in this theme).

In the longer run, you may want to look at panels/page_manager to get similar functionality with greater flexibility and 200% more chaos magic.

------
Personal: Outlandish Josh
Professional: Chapter Three

Sw33t!

That's pretty much what I have in our page.tpl.php file. I think we can live with having to modify it as needed for custom fields and any particular content types. I'd rather have a monster of a code snippet to wrestle with in one place than a bunch of them everywhere.

Thanks, Josh!

FWIW, here's what we did in the page.tpl.php file:

<?php
   
if(arg(0)=='node' && is_numeric(arg(1)) && arg(2)!='delete') {
        print
$node->content['body']['#value'];
       
/*    Add custom fields to "custom" pages */
       
if($node->type=='custom') {
                print
$node->content['field_custom_field1']['#children'];
                print
$node->content['field_custom_field2']['#children'];
                print
$node->content['field_custom_field3']['#children'];
        }
    else {
        print
$content;
        }
?>

Needed to add the "delete" arg because the delete button wasn't being shown (lol).

Right

Putting it in template.php is better too, because it keeps the tpl.php files more free from scary-looking php logic, and friendlier to markup-centric themers. Overriding variables is definitely better than switch/logic and alternate print() calls in tpl.php files.

------
Personal: Outlandish Josh
Professional: Chapter Three

Almost there...I think?

Okay, so I added this to our page preprocess, but it's not outputting anything. I even tried removing the conditions using just

<?php
  $vars
['content'] = $vars['node->content']['body']['#value'];
?>

...and still got nothing. Perhaps we are trying to do this too early?

When you mentioned doing this in the node, did you mean the node preprocess or the node.tpl?

Debuggin

Looks like you're not using the correct variable name. Try something like:

<?php
$vars
['content'] = $vars['node']->content['body']['#value'];
?>

The quick/dirty way to debug this is to use var_dump/print_r on the data you've got to work with. $vars is a big array. $vars['node'] should be an object. Etc.

------
Personal: Outlandish Josh
Professional: Chapter Three

That was it!

It was $vars['node']->content instead of $vars['node->content']. Perfect, it's all working now. We won't ever use comments on this site (so I'm told), so that's not an issue for now. If anything, I'm sure they can be added back using something along the lines of what's posted here.

Thank you, Josh. You're a helluva resource! =]

For those who may come across this issue, here's a generic sample of the snippet:

<?php
   
//    List the exceptions for arg(2)
    //    These pages need to be rendered "normally"
   
$vars['arg_exceptions'] = array('edit', 'delete', 'track', 'devel');

   
//    List the exceptions for certain content types
    //    If you have any content types that you don't want this to apply to,
    //    list them here.
   
$vars['ct_exceptions'] = array('exception_content_type_name_here','');
   
$vars['ct'] = $vars['node']->type;

   
//    Change the $content variable to display ONLY what's in the specified field (e.g. body)
   
if(arg(0)=='node' && is_numeric(arg(1)) && !in_array(arg(2),$vars['arg_exceptions']) && !in_array($vars['ct'],$vars['ct_exceptions'])) {
       
$vars['content'] = $vars['node']->content['body']['#value'];
       
//    Add custom fields for certain content types
       
if($vars['node']->type=='custom_type_name_here') {
           
$vars['content'] .= $vars['node']->content['field_custom1']['#children'];
           
$vars['content'] .= $vars['node']->content['field_custom2']['#children'];
           
$vars['content'] .= $vars['node']->content['field_custom3']['#children'];
        }
    }
?>

Still open to any other bits of advice regarding how to best write this, of course. Also, I suppose using switch logic would be cleaner, but I've learned that if/else is faster.

Also, you could use shorthands for all the different $vars being used. I just left it that way so you can see what's happening.

nobody click here