I want to have the most recent node (article, content, post, whatever) on the front page show as the full article, and then have the rest of the nodes show as teasers normally.

I did a lot of searching through Drupal.org, with as many good keyword combinations as I could think of, and I didn't find a straight up solution to this. So I hacked on the theme a little bit, and here's what I came up with.

The node.tpl.php file governs how each node is displayed. It gets some variables, including $content, passed to it from the rest of the engine, and shows the data for any given node. When the $content gets to the node.tpl.php file, it is already in either teaser or body format, so it is too late to make changes there - unless you go back to the database for another hit. So that's what I did.

This PHP snippet does the following

1) Check that this node is on the front page and is the very first one being printed.
2) If so, go back to the database and get the full content for the node.
3) Format it appropriately, and put it in for $content.

  <?php 
// added to make first node of front page print full,
// with teasers after that.
//
// per api.drupal.org/api/drupal/modules--node--node.tpl.php/6
// $id is the position of the node, increments with each output.  First is 1.
// $is_front says whether we are on the front page or not.

  if ($is_front && ($id=="1")):
    $nid=$node->nid;
    $body=db_result(db_query("SELECT body FROM {node_revisions} WHERE nid=%d", $nid));
    $content = check_markup($body);
  endif;
  ?>

This snippet can be placed anywhere in the node.tpl.php, as long as it is before the $content variable gets printed.

This seems to work as expected, as you can see on my site. But I have two questions for the community.

1) Are there any better, cleaner ways to do this besides going back to the database for another hit?
2) The "Read More" link is still there, since the article came out of the content engine as a teaser. I took a swing at removing the 'node_read_more' entry from the $links array, but that didn't work on the first few tries. Any suggestions there? (Perhaps the answer to question 1 will remove the need for question 2.)

Thanks for any help you can offer to make this a better solution!

Steve
--
http://etmeli.us/ - web development lab notebook
http://etmeli.us/build-this-site - Drupal 6 install tutorial

Comments

WorldFallz’s picture

I would think that normally most sites do this with views.

stevew’s picture

I fail at Views. I fought with it a little bit, but then found this other way, which for me was an easier path.

Edit: I should clarify a little. It is clear to me how to use Views to replace the whole front page with just teasers, or just full articles. What is not clear to me is how to make a View that shows a full first article followed by teasers for the next most recent posts.

If anyone has a Views recipe that does this, I'd be quite pleased to know about it!

WorldFallz’s picture

I do it all the time. I don't have time for a keystroke recipe, but here's the basics:

  1. enable the provided frontpage view and clone it (so you can leave the original intact).
  2. edit the 'page' display
  3. edit "items to display" -- set the first number to the number of teasers you want to display, and set the offset to 1 (that's key).
  4. add an 'attachment' display
  5. in 'attachment settings' set 'position' to 'before' and 'attach to' to be your front page page display
  6. edit 'items to display', click the 'override' button, and set number of items to 1 and offset to 0
  7. click the gear next to 'Row style: Node', click the 'override' button, and set build mode to teaser

That's from memory so I'm sure I missed something somewhere but it should be enough to give you the basics.

stevew’s picture

That helped a lot, thanks. Didn't know about how attachments worked, that'll be quite helpful as I go forward. (It has been a couple years since I rolled out a site, so I'm not really up on Views.) I did learn that if you have already added that node to a book structure, then the book navigation block will show up at the bottom of the node. I iterated through most of the settings that looked like they might affect it but didn't manage to ditch that block. Do you know of any pointers for getting rid of that? (That part is in its own div tag, so I could try to whack it that way, set display:none in the CSS.)

WorldFallz’s picture

Yeah-- there's probably better ways, but I usually just do it in css.

Melanie’s picture

WorldFallz, your directions worked perfectly. Now I am trying to get that page to appear as the landing page -- I am sorry I don't know the correct term, but the page that is simply webaddress.org. I tried to set path to home, to frontpage, and to leave it blank but none of those solutions worked.

WorldFallz’s picture

iiuyc, you can change the landing page to point to your view at admin/settings/site-information.

Melanie’s picture

thanks for helping a novice. Someday I will know enough to pay it forward.

jlyon’s picture

Anyone have a nice way to deal with pagers in this instance? If I set up a view and choose not to inherit the pager on the attachment, the first full post appears at the top of every page. If I choose to inherit the pager, then the attachment inherits the offset and the second post appears twice at the top of page 1 and the first post doesn't appear at all.

Thanks

cog.rusty’s picture

Try $body = $node->body;. It is already there and cached.

stevew’s picture

I tried that. I used the Contemplate module to see what variables were available from the $node object. Evidently, $node is built differently depending on whether it is a teaser or a full sized article. When a teaser node is sent to page.tpl.php, you can get to $node->content['body']['#value'], but it has only the teaser text loaded into it. That was why I decided I needed to go back to the database. Really the theme is too late for this, but as I said above, I fail at views and my cheap hack here mostly works. I just hope someone will have a more elegant solution.

cog.rusty’s picture

Damn, that should have been:

$propernode = node_load($node->nid);
$content =  check_markup($propernode->body);

No idea if this is more or less efficient than a new query. The node should be cached, but too much is going on. Not less hackish than a query, I think.

stevew’s picture

Thanks for the pointer to node_load, I'll read up on that and try and figure out which is less of a burden on the server.