Registering New Sidebars for Custom Page Templates The Smart Way

One of the cooler ideas for a new WordPress default Theme that’s come up has been the idea of including a not-so-blog-ish custom home page template with the Theme. Something optional that you could use if wanted your home page to look a little different. Maybe more of a traditional web site look (whatever that is) or a magazine look. Simply create a new page, assign this custom template to it, set it as your home page, and boom! New look.

I thought this was a great idea too. Especially if that custom page template was totally widgetized. Load up whatever dynamic content you want there with the Query Posts Widget or just use Text Widgets. The default styles of the new 2010 Theme can decide which of several widget areas is the ‘featured’ area and if you want something different—without wanting to change the markup—you can move things around with a Child Theme.

Great, right? Wrong.

You’d have to register new widget areas. Widget areas that would be confusingly unavailable if you weren’t using the custom home page template. Unless …

Here’s a really nifty function written up by Chris Gossmann that’ll check to see if a particular custom page template is active. Chris had to write a SQL query to get this to work so be thankful that he survived to tell us about it.

  1. function is_pagetemplate_active($pagetemplate = '') {
  2.  global $wpdb;
  3.  $sql = "select meta_key from $wpdb->postmeta where meta_key like '_wp_page_template' and meta_value like '" . $pagetemplate . "'";
  4.  $result = $wpdb->query($sql);
  5.  if ($result) {
  6.   return TRUE;
  7.  } else {
  8.   return FALSE;
  9.  }
  10. } // is_pagetemplate_active()

OK. Even by itself that function is kinda cool. There’s a few neat things you can do with it. Here’s one. Combine it with the following code for registering a new sidebar in the functions.php file of your WordPress Theme:

  1. function test_template_widgets_init() {    
  2.  if(is_pagetemplate_active('template-active.php')) {
  3.                
  4.   register_sidebar( array (
  5.    'name' => 'Test Widget Area',
  6.    'id' => 'test-widget-area',
  7.    'before_widget' => '<li id="%1$s" class="widget-container %2$s">',
  8.    'after_widget' => "</li>",
  9.    'before_title' => '<h3 class="widget-title">',
  10.    'after_title' => '</h3>',
  11.   ) );
  12.  
  13.  } // end test for active template
  14. } // test_template_widgets_init()
  15. add_action ( 'init' , 'test_template_widgets_init' );

Can you guess what that does? Using our new conditional function, is_pagetemplate_active(), we’re registering a new widget area only if, in this case, template-active.php is being used by one of our pages. Completely bypassing our earlier problem of widget areas potentially hanging around without a page for them to be displayed on.

What do you think? Pretty cool, huh? I see lots of really neat possibilities here for custom page templates in WordPress Themes and in Child Themes.

Don't forget: You should follow me on twitter here.

Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

16 Comments

  1. Posted December 20, 2009 at 12:22 pm | Permalink

    Hi. I gave this process a try and although it works beautifully, I found one small thing may be irritating to some users. Not sure how important this is, but I thought that I would bring it up for the sake of discussion. Here’s what I did and what happened:

    1. I change the page template of a page to one containing 3 widgetized areas.
    2. I navigate to /wp-admin/widgets.php and set up a widget for each area.
    3. I change the page template to one that has no widgetized areas.
    4. I change the page template back to one I chose in step 1.
    5. All of my widgets have been removed from the widgetized areas.

    I was wondering if you had an idea on how to keep all ’sidebars’ registered, yet hide them from widgets.php if they are not being used in a page template. I hacked around this for a bit, but found no viable solution

    • Posted December 20, 2009 at 1:46 pm | Permalink

      That’s a good question. I’d have to hack around myself. It’d also be nice to have a notification when you publish pages with a custom page template, reminding you that there are widget areas to configure with a link to the widgets page.

      • Posted December 20, 2009 at 2:00 pm | Permalink

        Right on. Please post back if you find a solution. I will do the same. The notification idea is great too. It may be pretty easy to hook into the admin_notices action and using the is_active_sidebar()function.

      • Posted December 21, 2009 at 3:52 pm | Permalink

        @Ian, I got a few minutes to play around with this again this afternoon and I think I may be on to something. I have tested the following code with 2.9 using the same process I outlined above. Unfortunately, this is not the cleanest solution due to the fact that I had to add a custom item to the array passed to register_sidebar(). The key is “page_templates” and its value is a numerically indexed array of page template file names.

        register_sidebar( array(
        'name' => __( 'Frontpage 1', PLATYPUS_LOCALE ),
        'id' => __( 'frontpage_1' ),
        'page_templates' => array( 't-frontpage-1.php' )
        ) );

        I created this function and hooked it into admin_head:

        add_action( 'admin_head', 'maybe_hide_sidebar_from_admin' );
        function maybe_hide_sidebar_from_admin( $pagetemplate = '' ) {
        global $wpdb, $wp_registered_sidebars;
        $templates = array();
        $active_templates = $wpdb->get_col( "SELECT DISTINCT( `meta_value` ) FROM `$wpdb->postmeta` WHERE `meta_key` = '_wp_page_template';" );
        if( $active_templates ) {
        foreach( $wp_registered_sidebars as $name => $data ) {
        if( isset( $data['page_templates'] ) && is_array( $data['page_templates'] ) ) {
        foreach( $data['page_templates'] as $template_name ) {
        $templates[] = $template_name;
        }
        }
        foreach( $templates as $template ) {
        if( !in_array( $template, $active_templates ) ) {
        unset( $wp_registered_sidebars[$name] );
        }
        }
        }
        }
        }

    • Posted December 21, 2009 at 11:18 am | Permalink

      @Michael Fields – I was dealing with the same problem for my custom theme that has something like 27 widgetized areas… it gets worse when you test a lot and keep changing templates that activate/deactivate different widget areas and dozens of widgets need to be re-placed into their sidebars over and over again. So what I did, I added a widget backup to the theme options – it basically saves the array of the widgets and the sidebars they assigned to. I also have a “restore” button. So, initially, when I place all my widgets in all the sidebars, I go to the theme settings and back them up. Then I can mess with templates and sidebars as much as I want because I can restore all the widgets with a single click of a mouse :)

      Hope this helps.

  2. Posted December 20, 2009 at 3:27 pm | Permalink

    This is very helpful. One of my Thematic child themes has a custom home page with nine widget areas:

    1. Home Top
    2. Home Left Top
    3. Home Left Left
    4. Home Left Right
    5. Home Left Bottom
    6. Home Right Tab Labels
    7. Home Right Tabs
    8. Home Below Tabs
    9. Home Bottom

    And they’ve worked very well, but occasionally I’ve gone to the home page to find it empty. And I suppose that turns out to be because the custom home page template somehow got disabled. Now I just need to figure out how to make the that template always available even when for some reason it’s not.

  3. Posted December 20, 2009 at 3:52 pm | Permalink

    The idea is nice but one thing that jumped out to me is the “like”s in the SQL. Why use Like instead of “=”? It’s going to be a lot slower and there’s no benefit.

    • Posted December 21, 2009 at 2:19 pm | Permalink

      Hi Ben,

      I did some tests here on my local system and can’t confirm your statement. The script using ‘like’ took between 0,0027 and 0,0036 seconds. A script using ‘=’ took between 0,0036 and 0,0042 seconds. Might be my test method or my system.

      Could you please guide me to a source that explains why using ‘=’ is faster than using ‘like’?

      Chris

  4. Posted December 21, 2009 at 5:18 am | Permalink

    Whats the point of registering it at the cost of 1 more SQL query?

  5. Posted December 21, 2009 at 12:11 pm | Permalink

    The even smartest way would be to use is_page_template() template tag. It would avoid 1 database query and 1 function (and its maintability).

    Anyway, that’s a good idea :)

    PS : the best way, keeping your SQL query, would have to eitheir add a LIMIT 1 in the query (especially as the meta table can contains lots of rows) or even better, doing a COUNT.

    • Posted December 21, 2009 at 1:24 pm | Permalink

      is_page_template() is a different thing altogether. It only tells you if you’re in any page template, or a particular one, not whether or not a particular page template is active.

      • Posted December 21, 2009 at 5:13 pm | Permalink

        Hell yay, I understood the subtle difference. Once a theme is registered/updated, ALL page templates should be stored in an option field. It’s not the thing changing all the time, without a version change.
        It would still avoid the, for me, useless query (hence it’s not cached).

    • Posted December 21, 2009 at 2:26 pm | Permalink

      Using count is to slow because it would run through all rows in WP_POSTMETA.

      An additionl parameter ‘limit 0, 1′ makes sense (take the first and display 1 — as far as I understood this parameter — sorry, I’m still learning SQL)

      The code should be:


      $sql = "select meta_key from $wpdb->postmeta where meta_key like '_wp_page_template' and meta_value like '" . $pagetemplate . "' limit 0, 1";

      Chris

    • Posted December 21, 2009 at 2:37 pm | Permalink

      @Chris – The first offset argument in your limit clause is actually not necessary. Usually, in queries like these, it will be expressed as “LIMIT 1″.

      MySql says this about it:

      With one argument, the value specifies the number of rows to return from the beginning of the result set…

  6. dougall
    Posted March 14, 2010 at 11:11 pm | Permalink

    Related to the page template subject, can someone please tell me how to add a different style sheet to a page template in the thematicfeaturesite child theme?

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution. In addition, you may find yourself fitter, happier and more productive. Comment away.

Subscribe without commenting