Posted by Marc Cepeda on December 2, 2009 at 9:06pm
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:
<?phpfunction 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:
<?phpif(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.