Custom Post Type Data in Sidebar widgets?

(note: this question was originally about Custom Fields, but @MikeSchinkel had a better solution involving Custom Post Types)

On my site I have several pages which I want to show the same data in the sidebar.
For instance, in a structure like this:

Read More
-Home
-Cars 
 -Volvo 850 overview 
 -Volvo 850 tech spec 
 -Volvo 850 pictures
 -Porsche 911 overview
 -Porsche 911 tech spec
 -Porsche 911 pictures
-Roads 
 -Route 66 overview 
 -Route 66 history 
 -Route 66 pictures
 -Pan-American Highway overview
 -Pan-American Highway history
 -Pan-American Highway pictures

I would like all the Volvo 850 pages to show the same data in the sidebar, all the Porsche pages to show a different set of data (for instance Speed, Maker, etc).

The Road pages would have their own set of data for each road. Cars and Roads would also have there own page template, and the way I figure it would get the right sidebar is something like this within sidebar.php:

if ( is_page_template('car-profile-template.php') ) :
// show car widgets

Here’s an example page, the Volvo 850 Pictures page. The same (left) sidebar should appear on the other Volvo 850 pages, while the stuff on the right is just page content.

|  Home   •Cars   Roads                                |
--------------------------------------------------------
|   Overview     |     Volvo 840 Pictures              |
|   Tech Spec    |    (some pics)                      |
|  •Pictures     |                                     |
------------------                                     |
| -Specs-        |                                     |
| Volvo 850      |                                     |
| Speed:150mph   |                                     |
| Maker:Volvo    |                                     |  
| Download PDF   |                                     |
------------------                                     |
| -Rating-       |                                     |
| Style:3        |                                     |
| Safety:5       |                                     |
| Reliablity:4   |                                     |
------------------                                     |

In this example, the two sidebar widgets, Specs and Rating should be getting their info from a Custom Post Type. Is there a method, which would be easy for the end-user to edit, which means that they would have to enter this custom data only once? It may not be necessary for each of the fields to be separate (ie all of Spec could be entered within an Editor field, and all of Rating could be put in Excerpt field.. maybe)

Related posts

Leave a Reply

3 comments

  1. UPDATE:

    Based upon the update of the question I think I need to explicitly state that what is asked in the question can be done with the answer below, just used custom fields in the “Car” custom post type for each of the items you want displayed on all pages for a given car.

    If you want to do it simply just hardcode the sidebar into the single-car.php template file I included below and then use your if statement to determine which content to display for the different URLs. You could go to the effort to widgetize your sidebar and develop a custom widget where the widget would pull the information for the current post ID, but why both unless you are building this as a theme for other people to use?

    There are actually a bunch of subtly different ways to accomplish this but the one I am suggesting should wonder wonderfully for your needs.


    Hi @cannyboy:

    I actually don’t know what the best way would be to share custom fields across posts. But that might just be the red flag you need. If something seems too hard maybe…

    An Alternate Approach?

    …you could shonsider architecting it differently? I think you’ll be much better off creating a Custom Post Type of “Car” and then you can store everything for each “page” into the one Car post type. Here are some sample URLs:

    http://example.com/cars/volvo850/  <-- overview
    http://example.com/cars/volvo850/tech-specs/
    http://example.com/cars/volvo850/pictures/
    

    Learning about Custom Post Types

    You can learn more about Custom Post Types at the answers to these questions:

    A Custom Post Type and A Rewrite Rule

    To implement Custom Post Types and the multiple pages you’d use code like the following which registers your “Car” Custom Post Type and then sets a rewrite rule for your car pages. Put this code in your theme’s functions.php file or in a plugin, whichever you prefer:

    <?php
    add_action('init','car_init');
    function car_init() {
      register_post_type('car',
        array(
          'label'           => 'Cars',
          'public'          => true,
          'show_ui'         => true,
          'query_var'       => 'car',
          'rewrite'         => array('slug' => 'cars'),
          'hierarchical'    => true,
          //'supports'        => array('title','editor','custom-fields'),
        )
      );
      global $wp,$wp_rewrite;
      $wp->add_query_var('car-page');
      $wp_rewrite->add_rule('cars/([^/]+)/(tech-specs|pictures)','index.php?car=$matches[1]&car-page=$matches[2]', 'top');
      $wp_rewrite->flush_rules(false);  // This should really be done in a plugin activation
    }
    

    A Car-specific Theme Template File

    Then you’ll need a Car-specific template file in your theme; the default name for this would be single-car.php. I’ve coded a starter template for you that renders all three of the URLs (the (overview), ‘tech-specs’ and ‘pictures’) in one template by using an if statement to determine which content to render:

    <?php get_header(); ?>
    <div id="container">
      <div id="content">
      <?php if ( have_posts() ): the_post(); ?>
        <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
        <h1 class="entry-title"><?php the_title(); ?></h1>
        <div class="entry-content">
    <?php if(is_car_techspecs()): ?>
      <a href="..">Back</a>
      <h1>Tech Specs</h1>
      The tech specs go here!
      <?php get_post_meta($post->ID,'_car_tech_specs'); ?>
    <?php elseif (is_car_pictures()): ?>
      <a href="..">Back</a>
      <h1>Pictures</h1>
      Car Pictures go here!
      <?php get_post_meta($post->ID,'_car_pictures'); ?>
    <?php else: ?>
      <ul>
        <h1>Overview</h1>
        <li><a href="tech-specs/">Tech Specs</a></li>
        <li><a href="pictures/">Pictures</a></li>
      </ul>
      <?php the_content(); ?>
    <?php endif; ?>
          <?php the_content(); ?>
        </div>
      <?php endif; ?>
      </div>
    </div>
    <?php get_sidebar(); ?>
    <?php get_footer(); ?>
    

    Note in the example above I’m being very simplistic with the use of get_post_meta(); real site would need to have a lot more complexity there.

    Template Tags a.k.a. Helper Functions

    Of course I used some template tags a.k.a. helper functions to minimize complexity in the template file in the if statement conditions. Here they are and you can put these in your theme’s functions.php file too:

    function is_car_techspecs() {
      global $wp_query;
      return is_car_page('tech-specs');
    }
    function is_car_pictures() {
      global $wp_query;
      return is_car_page('pictures');
    }
    
    function is_car_page($page) {
      global $wp_query;
      return (isset($wp_query->query['car-page']) && $wp_query->query['car-page']==$page);
    }
    

    Screenshots filled with Custom Post Type Love

    Once you have all that code in place and you’ve added a Car post like Volvo 850 you can get it to work like the following screenshots:

    Overview Page

    http://example.com/cars/volvo850/
    (source: mikeschinkel.com)

    Tech Specs Page

    http://example.com/cars/volvo850/tech-specs/

    Pictures Page

    http://example.com/cars/volvo850/pictures/

  2. I think someone might have already kind of answered this on the other question you posted (about parent pages / intermediate pages), but here’s what I think the best way to structure your data is, based on what you’ve described:

     - Home
     - Volvo 850 (overview)
       - Volvo 850 tech spec
       - Volvo 850 pictures
     - Porsche 911 (overview)
       - Porsche 911 tech spec
       - Porsche 911 pictures
    

    That way you only have to enter the meta fields once – on the parent page – and on the children pages you can pull that meta data from the parent:

    <?php echo 'Top speed: '.get_post_meta($post->post_parent,'Top Speed',true); ?>
    

    Of course, an even better way to organize this would be to have one single custom post type for each model of car which stores all of the car’s information, and display the various subpages based on a GET request that’s passed to the page and used in the page template as a switch to determine which template to display. That way you can completely avoid duplicating data, and make it easier to add more information to template later on…

    More details…

    I’ve done it a couple different ways. In one site where I had agents (company reps) as a custom post type, I used their posts to store all the data related to that person, but never actually displayed that page. Instead, I had an “Agent Listing” page, a “Agent Performance Record” page, and a “Contact This Agent” page, which were always called with a GET variable and displayed information out of the appropriate post. So the permalink would look something like site.com/agent-listing/?agent=john-smith.

    In another site , I set up all the information on one page and built all three views for that page into the page template. In your case, that would look something like site.com/cars/volvo-850/?pictures.

    And in the page template you would include a check for that variable near the top of the content:

    if ($_GET['pictures']) {
    
     // template for pictures page
    
    } else if ($_GET['tech-spec']) {
    
     // template for tech specs page 
    
    } else {
    
     // overview template
    
    }
    
  3. If you don’t want to create custom post types, and you simply want to include a custom sidebar for each page or post, you could use the Graceful Sidebar Plugin. This lets create custom sidebar content right from within the post or page edit screen using additional fields called graceful title and graceful content. These are then displayed in the sidebar area as a widget when this post or page is being displayed on your blog. More information on this plugin is available at http://www.mlynn.org/graceful-sidebar-plugin