Themeing CCK & styling node.tpl.php. is there PHP code to show fields only if there is data entered?

Events happening in the community are now at Drupal community events on www.drupal.org.
abelb's picture

I posted this on the main drupal theme development forum with no response so i thought i might try my portland buddies...

I am developing a theme for a site that has multiple listings. The site had a landing page with a summary menu produced by creating a view with an argument of city (organizes listings by city). Upon clicking on the city, the user sees, for example, all the restaurants of that particular city. Upon clicking on the restaurant name, the user sees the node page with the body output of the all fields created using CCK.

these links show the process:
http://vc.andreaburton.com/eat
http://vc.andreaburton.com/pittsboro
http://vc.andreaburton.com/node/194

I am trying to figure out the best way to theme the node pages. There is not data for every single field in every single node. I have created a custom node-eat.tpl.php to style this page but the code for the field shows up even if there is no data. I have attached the code below. (if you look at the source code of http://vc.andreaburton.com/node/194 you will see an empty <h3></h3> that is placed there for a tagline. this node does not have a tagline thus no data appears. it just seems bobo to have empty html tags in a template with no data in them.)

I have even tried contemplate but it seems to create very similar code output.

I have had some success creating a content-field.tpl.php file for each field. The code here knows when to not show a field if there is no data using !$field_empty variable. but with a site with hundreds of fields, it seems a little crazy to make a separate file for each field.

is there any code to basically say, hey drupal, im in the node.tpl.php, if there is no data for any of the CCK fields don't output it in the theme?

also, im wondering if there is any way i can put the detail page out as a view. I was able to create the view with the summary ascending using the city as an argument and creating the table view with the title, city and website, (http://vc.andreaburton.com/pittsboro) but when i went to create a second argument (i was trying to go with title name), i got stuck when i was trying to have the title of a node link to a view created by an argument. please no judgement here, i am swimming in new territory so i may be talking crazy. i figured i could them style the views theme and it would filter out the fields that had no data. but it seems contradictory because shouldn't i just use the node pages and style those instead of creating a view of the detail page?

thanks for any help. im really trying to wrap my head around the proper way to do this.

thanks!
andrea b.
code from the node-eat.tpl.php

<div id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?>"><div class="node-inner" id="detail-page">

  <?php if (!$page): ?>
    <h2 class="title">
      <a href="<?php print $node_url; ?>" title="<?php print $title ?>"><?php print $title; ?></a>
    </h2>
  <?php endif; ?>

  <?php if ($unpublished): ?>
    <div class="unpublished"><?php print t('Unpublished'); ?></div>
  <?php endif; ?>



  <div class="content">
    <div id="column-1">
      
        <h3><?php echo $node->field_shortdesc[0]['view'];?></h3>
  
  
       <ul>
        <li><strong><?php echo $node->field_phone[0]['view'];?></strong></li>
        <li><a href="mailto:<?php echo $node->field_email[0]['value'];?>"><?php echo $node->field_email[0]['view'];?></a></li>
        <li><a href="<?php echo $node->field_website[0]['value'];?>">View Website</a></li>
       </ul>
  
        <ul>
            <li><strong>Address:</strong> <?php echo $node->field_address[0]['view'];?>, <?php echo $node->field_city[0]['view'];?>, <?php echo $node->field_zip[0]['view'];?></li>
        <li><strong>Mailing Address:</strong> <?php echo $node->field_mailingaddress[0]['view'];?>, <?php echo $node->field_city[0]['view'];?>, <?php echo $node->field_zip[0]['view'];?></li>
        </ul>
  
    <p><?php print $node->content['body']['#value'];?></p>
    <h4>Amenities</h4>
    <p><?php echo $node->field_amenitiesnotes[0]['view'];?></div>

  <?php print $links; ?>

  <div id="column-2">
     <span><?php echo theme('imagecache', 'node_image', $node->field_nodeimage[0]['filepath'],  $node->title, $node->title, array('class' => 'node-image')); ?></span>
       </div>
  </div>


  <?php if ($terms): ?>
    <div class="meta">
      <?php if ($terms): ?>
        <div class="terms terms-inline"><?php print t(' in ') . $terms; ?></div>
      <?php endif; ?>
    </div>
  <?php endif; ?>

</div></div> <!-- /node-inner, /node -->

Comments

Try this

bgilday's picture

Try checking to see if the field exists before printing it as output. So, let's take your Tagline issue as an example.

You currently have the following code above:

<h3><?php echo $node->field_shortdesc[0]['view'];?></h3>

Try changing that to the below code and confirm that the output only shows if the field actually exists (i.e. your h3 tags should no longer display if there's no data in the field for that node). If this works, you should be able to apply the same pattern to other fields.

<?php
if ($node->field_shortdesc[0]['view']) { ?>

<h3><?php print $node->field_shortdesc[0]['view'] ?></h3>
<?php } ?>

This should work via either contemplate or node.tpl.php.

I hope this helps.

Brian Gilday
Managing Partner
Aha Consulting
www.ahaconsulting.com

Brian Gilday
Municode
www.municode.com

works like a charm

abelb's picture

thank you so much brian! exactly what i was looking for. i need to learn php asap.

also, you helped me a few weeks ago with date formatting and it has been saving my life creating calendar views for the same site.
just wanted to thank you for that as well.

andrea

One things that I find

mikey_p's picture

One things that I find really helps, is to add preprocess_functions to my template.php to make the template a bit easier to understand. For instance:

<?php
function themename_preprocess_node(&$vars) {
  if (
$vars['node']->type == 'my_type') {
   
// Prepare mailto link
   
$vars['mail'] = $vars['field_email'][0]['value'];
   
$vars['meilto_link'] = l($vars['field_email'][0]['view'], 'mailto:'. $vars['field_email'][0]['value']);
  }
}
?>

Lets you put simpler tags in your template:

<?php if ($mail): ?>
  <li><?php print $mailto_link; ?></li>
<?php endif; ?>

This is especially handy for long and complex conditions (if field a and b, then c, but not if d) or if you have to combine fields in interesting ways, (location_city = Portland and location_state = OR, but I can combine those in preprocess so that $node_location in the template = city, ST).

Hope this helps some.

great tip mikey_p

bgilday's picture

Adding snippets to template.php patterned after your above example will certainly make the code in contemplate / node.tpl.php much cleaner. Very nice tip.

Brian Gilday
Managing Partner
Aha Consulting
www.ahaconsulting.com

Brian Gilday
Municode
www.municode.com

abelb's picture

would the code just be

<?php
function themename_preprocess_node(&$vars) {
  if (
$vars['node']) {
   
// Prepare mailto link
   
$vars['mail'] = $vars['field_email'][0]['value'];
   
$vars['meilto_link'] = l($vars['field_email'][0]['view'], 'mailto:'. $vars['field_email'][0]['value']);
  }
}
?>

Sure, as long as all your

mikey_p's picture

Sure, as long as all your content types have the required fields. In this case, you probably don't need to check for $vars['node'] since you are in hook_preprocess_node, and are actually using the field_name variables.

it's a bit old discussion,

monti's picture

it's a bit old discussion, but i wonder if node-eat.tpl.php or any other node-typename.tpl.php could be used to add a related view to the $content.
cheers !

Use the Views API

tylerwalts's picture

<?php
$view
= views_get_view('viewname');
print
$view->execute_display('default', $args);
?>

More here: http://drupal.org/handbook/modules/views

-=-

Edit: I was just looking back at this thread, and since my original post, I have moved toward using the views_embed_view() function that mikeyp describes below.

  • Tyler

Thanks + question

monti's picture

Wow! that simple ? Thanks Tyler !

I want to check it out already, but i'll have to wait until tomorrow.

Another question, if we're already here: is there any way to pass an argument of the current node to the view?

Yes, Tyler mentioned one way,

mikey_p's picture

Yes, Tyler mentioned one way, the other simple way is to use views_embed_view(). This function takes the view name, display id, and any additional function arguments are passed to the view as arguments.

As always, putting this code in a preprocess function in your template.php of module code, is a good idea to keep your templates simpler and easy to read.

am not sure i got what you

monti's picture

am not sure i got what you say, mikey_p -

I have got different nodes of the same content type, and am looking for a method to embed different views (or single view with different arguments) into these nodes' $content.

I am not familiar with the function, but my understanding is that views_embed_view() is not quite what i need, right?

views_embed_view() is exactly

mikey_p's picture

views_embed_view() is exactly what you need. In pseudo code:

<?php
// @file template.php of your theme

MYTHEMENAME_preprocess_node(&$vars) {
 
// Change this to reflect the name of your content type
 
if ($vars['node']->type == 'NODETYPE') {
   
// VIEWNAME is the name of the view, DISPLAY_ID is the id of the display, use 'default' if
    // you haven't added any displays, and the third argument will pass the node id to
    // the view as an argument. You could use any value from the node object here.
   
$vars['my_view'] = views_embed_view('VIEWNAME', 'DISPLAY_ID', $vars['node']->nid);
  }
}
?>

Then in your template file (node-NODETYPE.tpl.php), all you need to use is:

<?php if ($my_view): ?>
  <div class="my-view">
    <?php print $my_view; ?>
  </div>
<?php endif; ?>

it is not working

rubab.11's picture

i copied node.tpl.php and rename it node-story.tpl.php and want to show node detail via 2 views (to show detail in different layout from note.tpl.php)

for this i write following function in template.php

function THEMENAME_preprocess_node(&$vars) {
if ($vars['node']->type == 'story') {
// Prepare mailto link
//echo $vars['node']->type;
$vars['news_detail_pic'] = views_embed_view('news_detail_pic', 'default', $vars['node']->nid);
$vars['news_detail'] = views_embed_view('news_detail', '', $vars['node']->nid);
}
}

and in node-story.tpl.php i write

<?php
if ($news_detail_pic):
      print
$news_detail_pic;
endif;
?>

<?php
if ($news_detail):
    print
$news_detail;
endif;
?>

actually i need detail picture and news title in top div and in 2nd div i need complete news that's why i need two views

i am using drupal 6.x

please reply me soon

if it really works, I love

monti's picture

if it really works, I love you and i love Drupal more then ever. so clean! amazing!

I'll post back here tomorrow morning.

p.s.: don't worry, i am happily married :)

works like a charm

monti's picture

excellent ! great ! magnificent ! terrific ! wonderful ! exciting ! astonishing ! exceptional ! no more words :)

Thank You

how do I display the field title?

justclint's picture

Hey guys, this article got me up and running on theming my node-mycontent.tpl.php file.

But Im having trouble printing out the title of the field.

In theory Id like to do something like:

<?php


print "<b>" . $node->field_first_name['title'] . "</b>" . $node->field_first_name['0']['value'];
?>

So the out put would expect would be:
First Name: John Doe

I've been searching hi and low for the solution but just cant seem to get it.

Thanks!

While of course you could

mikey_p's picture

While of course you could hard code the label in your template, you could also use content_fields() to get the field info and use the label from that.

<?php
$field_info
= content_fields('FIELD_NAME', 'TYPE_NAME');

print
filter_xss_admin($field_info['widget']['label']);

// Print the field, etc....
?>

You can get the field and content type names from the manage fields page in the content types administration section.

Of course this requires that

mikey_p's picture

Of course this requires that CCK is enabled, but this is assuming that you are using CCK fields in the first place.

Of course this requires that

mikey_p's picture

Of course this requires that CCK is enabled, but this is assuming that you are using CCK fields in the first place.

You mean the label of the

nonsie's picture

You mean the label of the field? Look under your node type's display settings and make sure it's not set to hidden.

similar question

egill80's picture

i don't want to hijack the discussion but i have similar question to this.

I have a product page template, called node-product.tpl.php which is content type product where i am selling books. i have a another content type called 'author' where a have some additional fields such as about author, bibliography, portait so on.

in my "product" content type i have a node reference field field_author which is referenced to each author in "author" content type, and field_author i.e. the name of the author is displayed on the product node.

I want to integrate specific fields within "author" content type (bibliography, portrait, about author) into my product.tpl.php file, and print them out there.

i understand that this has to be done by creating preprocess function as mentioned above. how can i do that??

this means i have to create some kind of statement function saying that - i want drupal to identify the name of the author, and by that find the 'author' content type node which match the author and, from that get the desired fields i want (bibliography, about author etc.)

any help is highly appreciated, been struggling with this for days

thanks

i guess it must look

egill80's picture

i guess it must look something like:

<?php
 
function themename_preprocess_node(&$vars) {
    if (
$vars['node']) -> type == author

if  ($node->field_author[0]['view']) exist
        
(get $content_type->author)

<?
php print $node->content['body']['#value']
<?
php print $node->field_biography
</php endif
?>

but i cant get it to work because i cant pull fields from another content "author" type into my product.tpl.php

this might help...

abelb's picture

im still learning node references but this video of Node References from Mustardseed media might help:
http://mustardseedmedia.com/podcast/episode37

He is using the Views Attach module http://drupal.org/project/views_attach to create Node Content that will attach onto the content type that is being referenced.

I haven't tried it out but it seems like you can pull the fields you want from author and attach via this method to your product pages.

hope this helps!

thanks alburton but not

egill80's picture

thanks alburton but not exactly what i am looking for

i think maybe i can use the node_load option.
then my code wouyld be something like:

<?php

// if  ($nodeproduct->field_author[0]['view'])
// $nodeauthor=node_load($nodeproduct->field_author[0]['view'])
<?php // print $nodeauthor->content['body']['#value']

?>

i managed to solve the

egill80's picture

i managed to solve the problem and i want to post it if anybody has similar issues to solve
the code was actually much lighter than i thought.

as stated earlier i used to node_load function to get the nid.
http://api.ubercart.org/api/function/node_load

just created a variable and then printed it below

the code;

<?php

$nodeauthor
=node_load($node->field_author[0]['nid']);
print
$nodeauthor->body;

?>

by this you can gain control over your node as desired.
not sure if its the right way but it worked for me

There's a lot being written

jnicola's picture

There's a lot being written in here, and perhaps I am missing something, but the solution should be as simple as...

if $variable != null {
print $thatVariable;
}

If the variable is null, it won't be rendered...

Jesse Nicola -- Shredical six different ways to Sunday! -- My Portfolio

output problem

karthik085k's picture

i have created a form as transport selection....after entering the values i am not able to see the output..
in themes if i delete yhe file node.tpl.php....im getting the output....wht can i do?im using acquia_marina theme..

check HTML CCK fields for content

urbanlegend's picture

While Jesse's comment hits the nail on the head, this does not work well for elective HTML fields in a content type. While selecting to strip HTML from within the view is one alternative, that will shred intended markup for those fields that were submitted.
In some cases, while the field appears blank, because of CKEditor or other wysiwyg editors, the content may actually contain
. A good workaround then, is to check the length of the field's value, something like (for a node-xxx.tpl.php):

if(strlen($field_cck_fieldname[0]['safe'])>9){
print $field_cck_fieldname;
}

In my case, the 9 is not arbitary - I checked what appeared to be empty fields, but actually had a sole
tag, and their strlen returned 8.

You could also just pull out

jnicola's picture

You could also just pull out the
from the equation!

str_replace('
','',$thatstring)

Jesse Nicola -- Shredical six different ways to Sunday! -- My Portfolio

Portland (Oregon)

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: