Sidebars Class for Thesis

Adding new sidebars (widget areas) can sometimes be a bit of a pain with the Thesis theme, so this class not only adds the concept of sidebar sets, but also makes adding them require just two lines of code per set.

Set up

  1. Create a new folder inside the Thesis custom/ folder called classes
  2. Copy the following to a blank file and save it to custom/classes/GT_Sidebars.php:

<?php
/**
 * Allows additional sidebars to be added, with the option of only showing or
 * not showing them on specified pages
 *
 * @package GT_Sidebar
 * @author Gary Jones
 * @version 2010-04-29
 * @since 2010-02-16
 */
class GT_Sidebars
{
    /**
     * @var int
     */
    protected $_numberOfSidebars;

    /**
     * @var string
     */
    protected $_titleOfSidebars;

    /**
     * @var string
     */
    protected $_beforeTitle;

    /**
     * @var string
     */
    protected $_afterTitle;

    /**
     * @var string
     */
    protected $_template;

    /**
     * Stores the list of post/page IDs the sidebar should be shown on
     * @var array
     */
    protected $_includes = array();

    /**
     * Stores the list of post/page IDs the sidebar should not be shown on
     * @var array
     */
    protected $_excludes = array();

    /**
     * Global $wp_query supplied by WordPress
     * @var mixed
     */
    protected $_globalQuery;

    /**
     * Set our options
     * @param int $numberOfSidebars Number of sidebars to create in one go
     * @param string $titleOfSidebars Name to give to all sidebars created in one go
     * @param string $beforeTitle HTML code before each widget title in the sidebar
     * @param string $afterTitle HTML code after each widget title in the sidebar
     */
    public function __construct($numberOfSidebars, $titleOfSidebars, $beforeTitle = '<h3>', $afterTitle = '</h3>')
    {
        $this-&gt;_numberOfSidebars = $numberOfSidebars;
        $this-&gt;_titleOfSidebars = $titleOfSidebars;
        $this-&gt;_beforeTitle = $beforeTitle;
        $this-&gt;_afterTitle = $afterTitle;
        $this-&gt;_globalQuery = $GLOBALS['wp_query'];

        $this-&gt;_template = 1;
        $this-&gt;_register();
    }

    /**
     * Choose which template to use.
     *
     * @param int $template Number following _getOutput_ to determine which template to use for a set of sidebars
     */
    public function setTemplate($template = 1)
    {
        if ( is_int($template) &amp;&amp; function_exists($this-&gt;_getOutput_.$template) ) {
          $this-&gt;_template = $template;
        }
        return $this;
    }

    /**
     * Choose which posts/pages to show the sidebar on. If this option is not set, then sidebar will appear on
     * all posts and pages. Comma-seperated string.
     *
     * @param null|string
     */
    public function setInclude($ids = null)
    {
        if ( is_null($ids) ) {
          return $this;
        }
        $explode = explode(",", $ids);
        foreach ($explode as $id) {
            $this-&gt;_includes[] = trim($id);
        }
        return $this;
    }

    /**
     * Choose which posts/pages to not show the sidebar on. Comma-seperated string.
     *
     * @param null|string
     */
    public function setExclude($ids = null)
    {
        if ( is_null($ids) ) {
          return $this;
        }
        $explode = explode(",", $ids);
        foreach ($explode as $id) {
            $this-&gt;_excludes[] = trim($id);
        }
        return $this;
    }

    /**
     * Output the new sidebars by attaching it to the supplied action hook
     *
     * @param string $hook Name of the action hook to attach it to
     * @param int $priority Determines the order of execution within the action hook (10 is default)
     */
    public function hook($hook, $priority = 10)
    {
        if ( !empty( $hook ) ) {
            add_action( $hook, array( &amp;$this, '_getOutput_' . $this-&gt;_template ), $priority );
        } else {
            throw new Exception('The "hook" method must contain the name of an action hook. e.g. $yoursidebars-&gt;hook(\'hook_name_here\');');
        }
        return $this;
    }

    /**
     * Register the sidebars with WordPress
     */
    private function _register()
    {
        if ( $this-&gt;_numberOfSidebars &gt; 1 ) {
          register_sidebars( $this-&gt;_numberOfSidebars, array(
              'name' =&gt; $this-&gt;_titleOfSidebars . ' %d',
              'before_title' =&gt; $this-&gt;_beforeTitle,
              'after_title'=&gt;$this-&gt;_afterTitle
          ));
        } else {
          register_sidebar( array(
              'name' =&gt; $this-&gt;_titleOfSidebars,
              'before_title' =&gt; $this-&gt;_beforeTitle,
              'after_title'=&gt;$this-&gt;_afterTitle
          ));
        }
    }

    /**
     * Return the markup
     * We're technically public, as the hook uses this function for it's callback, but it's not supposed to be for direct coded consumption.
     * If you want a different template, then copy this function, rename it to _getOutput_2, and use the setTemplate() method before the hook() line.
     */
    public function _getOutput_1()
    {
//      echo '<pre>';
//        var_dump($this-&gt;_globalQuery-&gt;post);
//        echo '</pre>';
        /*
         * If some includes have been set AND our post ID is one of them, OR no includes have been set then ...
         */
        if ( $this-&gt;_isShowable() ) {
            ?&gt;
            &lt;div id=&quot;_titleOfSidebars) ); ?&gt;_sidebar" class="sidebar"&gt;
            &lt;?php
            for ($i=1; $i_numberOfSidebars; $i++) {
                ?&gt;
                &lt;div id=&quot;_titleOfSidebars) ) . '_' .$i;?&gt;" class="widget_column widget_column__numberOfSidebars;?&gt;"&gt;
  	              <ul class="sidebar_list">
                    _numberOfSidebars &gt; 1 ) {
                      dynamic_sidebar($this-&gt;_titleOfSidebars . ' ' . $i);
                    } else {
                      dynamic_sidebar($this-&gt;_titleOfSidebars);
                    }	?&gt;
  	              </ul>
                </div>

        </div>
        _includes)
                &amp;&amp;
                (
                  in_array($this-&gt;_globalQuery-&gt;post-&gt;ID, $this-&gt;_includes)
                  ||
                  in_array($this-&gt;_globalQuery-&gt;post-&gt;post_name, $this-&gt;_includes)
                  ||
                  (
                    $this-&gt;_globalQuery-&gt;is_home
                    &amp;&amp;
                    in_array('home', $this-&gt;_includes)
                  )
                )
                ||
                !count($this-&gt;_includes)
              )
              &amp;&amp;
              (
                !in_array($this-&gt;_globalQuery-&gt;post-&gt;ID, $this-&gt;_excludes)
                &amp;&amp;
                !in_array($this-&gt;_globalQuery-&gt;post-&gt;post_name, $this-&gt;_excludes)
                &amp;&amp;
                !(
                  $this-&gt;_globalQuery-&gt;is_home
                  &amp;&amp;
                  in_array('home', $this-&gt;_excludes)
                )
              )
            ) {
          return true;
        }
        return false;
    }
}

Don’t worry too much about what that all means – once you’ve saved it, you’re unlikely to ever need to look at it again.

Add the following to your custom_functions.php:

require_once 'classes/GT_Sidebars.php';

Footer Sidebars Example

To create a new set of 3 footer sidebars, you can simply add the following to your custom_functions.php:

$footersidebars = new GT_Sidebars(3, 'Footer Sidebar');
$footersidebars-&gt;hook('thesis_hook_before_footer');
  • The $ variable (here, it’s $footersidebars) can be anything you want – it simply links the two lines of code together.
  • The 3 represents the number of sidebars in the set.
  • The Footer Sidebar is the name of the sidebar that appears in the admin area. It is also used as the IDs of areas, made safe by making the name lowercase, and replacing spaces with underscores.
  • The thesis_hook_before_footer is the hook to which the sidebar is placed.

The HTML output from this (what appears to the browser at the front-end) would be:

<div class="sidebar">
  <div class="widget_column widget_column_3">
    <ul class="sidebar_list">
      <!-- Widgets as list items appear here -->
    </ul>
  </div>
  <div class="widget_column widget_column_3">
    <ul class="sidebar_list">
      <!-- Widgets as list items appear here -->
    </ul>
  </div>
  <div class="widget_column widget_column_3">
    <ul class="sidebar_list">
      <!-- Widgets as list items appear here -->
    </ul>
  </div>
</div>

Single Sidebar Example

Say we wanted to add a single sidebar before the multimedia box, and put some widgets in there, the custom_functions.php would have:

$additionlWidgetSidebar = new GT_Sidebars(1, 'Additional Widgets');
$additionlWidgetSidebar-&gt;hook('thesis_hook_before_sidebars');

Set Include Example

Sometimes, you only want the sidebar to show up on certain posts or pages. The setInclude() method supports specifying the post or page via it’s ID, it’s name, or in the special case of the homepage, with ‘home’. Specify multiple pages at once by splitting the identifiers with commas. In the following example, the widget will only appear on post/page 55, on the About page, and the homepage.

$conditionalSidebar = new GT_Sidebars(1,'Conditional Sidebar');
$conditionalSidebar-&gt;setInclude('home,55,about')-&gt;hook('thesis_hook_before_sidebars');

If no setInclude() is given, then the sidebar will show on all posts/pages (unless excluded, see below).

Set Exclude Example

Conversely to above, sometimes you want the sidebar to show up on all pages except certain posts or pages. The setExclude() method also supports specifying the post or page via it’s ID, it’s name, or in the special case of the homepage, with ‘home’. Specify multiple pages at once by splitting the identifiers with commas. In the following example, the widget will appear on all posts and pages except the Contact page.

$conditionalSidebar = new GT_Sidebars(1,'Conditional Sidebar');
$conditionalSidebar-&gt;setExclude('contact')-&gt;hook('thesis_hook_before_sidebars');

Set Template Example – Advanced Usage

Some may not like the default output structure, or may want to have multiple structures. Not a problem! From within the custom/GT_Sidebars.php file, copy and paste the _get_output_1 function, and call it _get_output_2, then tweak it to suit the structure you want. You can now call it like:

$aftercontentsidebars = new GT_Sidebars(4, 'After Content');
$aftercontentsidebars-&gt;setTemplate(2)-&gt;hook('thesis_hook_after_content');

Styling

Without some extra styles, the sidebars in a set will all just following each other vertically – not what you probably wanted. To bring them all up side-by-side, you can add the following to your custom.css:

.custom .sidebar div.widget_column {float:left;margin:5px 3px 0 0;padding-left:10px;text-align:left;}
.custom .sidebar div.widget_column_1 {width:98%;}
.custom .sidebar div.widget_column_2 {width:47%;}
.custom .sidebar div.widget_column_3 {width:31%;}
.custom .sidebar div.widget_column_4 {width:23%;}

Values are just less than the obvious numerical ratios (100%, 50%, 33%, 25%, etc), as with the extra margin and padding, some browsers may mis-calculate and wrap the last sidebar underneath. Tweak these values to suit. You should have enough CSS hooks to target any specific sidebar set and any specific sidebar.

Future

Dude that is awesome!@gregrickaby

The whole purpose of a class like this, is to act as a wrapper for all that messy code, and provide a more uniform and simplified interface that even non-coders can follow. This class still has some bits needing adding to it (like extra conditional options), but for registering multiple sidebars, in sets, structuring the output, hooking them into Thesis, and choosing which posts and pages they appear on, you can’t get much better than two lines of code :-)

Update 2010-04-14: Tweaked the message in an Exception so it doesn’t cause a parse error once this has been copied and pasted into a class file.

Update 2010-04-29: Added the setInclude() and setExclude() features.

Comments

  1. Wow Gary, that’s brilliant. This makes the creation of multiple sidebars and widget areas on a site so much simpler. Thanks for posting this.

  2. lynn says:

    HELP HELP HELP… What is the easiest software to create the blank file for GT_Sidebars.php. I use mac and tried using texteditor, then when I saved it I changed to .php, but got a parse error line 94.

    Are there any other ways to do it?

    • Gary says:

      Hi Lynn,

      Which file did the error say it was from – GT_Sidebars.php? Or your custom_functions.php?

      I don’t use a Mac, but if you save it as a text file (.txt on a PC), you should be able to rename it and change the extension. If you can’t do it locally, then you should be able to upload it to the custom/classes/ folder, then rename it via your FTP client.

  3. lynn says:

    Gary-
    The error was in the GT_sidebars.php file. Which I thought odd – I mess up the custom_function.php all the time – LOL!

    I did use my text editor which saved as .rtf (though none of the color coding comes through (does that matter?) and uploaded it and then renamed in my FTP client as you said.

    Any ideas or should I just try again?

    • Gary says:

      Which text editor were you using?

      You should have the option of saving to plain text file, rather than rich text file. It doesn’t matter about the lack of colour coding, but .rtf may be making changes when it saves.

      If it’s still happening, can you post lines 93, 94 and 95 here, so we know which lines you’ve got. From my file, I get line 94 as simply two closing brackets and a semi-colon. Perhaps if you can paste the actual error message too, then we’ll find the cause.

  4. lynn says:

    Fatal error: Class ‘GT_Sidebars’ not found in /home/lmmahoney/mavenofsavin.com/wp-content/themes/thesis_17/custom/custom_functions.php on line 94

    OK i did that – changed to plain text and now I get this error. Could it be because my folder is themes/thesis_17/custom/classes – is your code not looking there?

    • Gary says:

      And can you post the snippet of code you’ve entered into your custom_functions.php file?
      I suspect you’ve either forgotten the:

      require_once 'classes/GT_Sidebars.php

      line, or made a typo in it (be sure that you get capitalisation correct too).

  5. lynn says:

    AHHH – you are right – I have tried and deleted so many times I forgot to put it back in – let me try again – THANKS

  6. lynn says:

    Gary – YOU ROCK!!! Thank you so much! Cannot wait to add content!

  7. Neil says:

    I love this Gary, thanks very much, and it all works great – until I get ambitious and start adding your conditionals. For some reason it all breaks when I add:
    $conditionalSidebar = new GT_Sidebars(1,’Conditional Sidebar’);
    $conditionalSidebar->setInclude(‘home,55,about’)->hook(‘thesis_hook_before_sidebars’);
    The thing is I can’t really find many references to setInclude to try and work out why it won’t work. Every time I add it, it breaks the site.
    Do you know where I could read up about setInclude() to help me work out what I’m doing wrong? So far I am just copying and pasting from you (although to be precise, I did type in once in case I had a formatting problem) and it’s not working for me.
    many thanks

    • Gary says:

      When it breaks, do you get an error message at all?

      Are you sure you’re running PHP5? I’ve found that PHP4 doesn’t seem to like the chained commands, so something like:

      $conditionalSidebar = new GT_Sidebars(1,'Conditional Sidebar');
      $conditionalSidebar->setInclude('home,55,about');
      $conditionalSidebar->hook('thesis_hook_before_sidebars');

      …is needed where customisation is on it’s own line.

      The setInclude() method is not a built-in-in function – it’s purely what I’ve created and added to the class – you can see it starting on line 95. In short, it takes a single string argument (and ignores everything else if it’s empty), splits up the string by the comma, and adds each of the values to an array.

      When it comes to getting the output, there’s a check for whether the sidebar is showable on that page. This check is done in the _isShowable() function by looping through the array values to see if it matches the current page reference.

      If you can include any error messages, along with the actual code you’re trying in your custom_functions file, then we’ll go from there :)

      • Neil says:

        I am an idiot. It’s all sorted, thanks Gary.
        I was using your earlier version of the GT_Sidebars.php code – and of course that didn’t have your additional setInclude() function. I didn’t notice until you mentioned line 95 and I realised we were looking at different things!
        Thanks again.
        I wonder if there is anything like this sidebars class solution that would work for when you have a lot of custom fields and want to display them differently in different places. Just a thought :-)
        thanks
        N.

        • Gary says:

          Ah, glad we got that sorted out :)

          So, you’re after something simple that would pull a custom field for a post, and display it either at a hook or via a shortcode? Should be possible :)

          • Neil says:

            Well I don’t have any specific requirement right now but I wondered if this approach might help people with a mass of custom fields and a variety of output needs. Could be really good.
            Maybe they could pull up a particular combination of custom fields via a shortcode in a $conditionalSidebar! :-)

            cheers
            N.

  8. Stephen says:

    Hi Gary,

    Nice tutorial you got there! I found your link on the Thesis forum – I had a few problems getting it to work but that was because I didn’t read your guide properly and just started copying and pasting like a coding numpty!

    Thanks for sharing.

    • Gary says:

      I can’t be held responsible for people not reading (!) but it does mean perhaps I need to make some things a little clearer within the tutorial. Which bit was it you unintentionally skipped over?

      (Main thing is, with careful reading, you *did* get it working :) )

      • Stephen says:

        My eyes glazed over when I saw all that the code! My initial mistake was not creating the additional folder/file and just adding the code underneath “Footer Sidebars Example” to the custom_functions.php file. Once I saw the error message I went back and re-read the post from the top and soon got it fixed.

        Great piece of code though, works really well.

        BTW – I checked your site for a way to subscribe by email but you don’t have that option, which is a pity. I take a lot more notice of my emails than I do of my RSS reader.

        • Gary says:

          OK, thanks for that useful feedback. When I get chance, I’ll make it clear what the first steps need to be.

          Each post has a “Notify me of comments via email” option, so select that if you wan to get notified of replies :)

          • Stephen says:

            Yes, I ticked the “Notify” button. I meant notification of new posts – it looks like you have a lot of useful stuff on your site, but I don’t think I would visit on a regular basis to see what was new, however, I think I would visit if an email popped into my inbox telling me about a nifty new piece of code you had written that would be useful to me.

            I use Feedburner to do this on a couple of sites and it works really well (and it’s free!)

          • Gary says:

            A couple of subscription items have now been added (bottom of sidebar).

  9. Paula says:

    Thanks for this! I have created two sets of sidebars, one for the traditional sidebar area and the other for the footer. Now I’d like to make only the footer sidebars align horizontally, but I’m confused about how to make them separate for styling purposes. Could you expand on how to make separate set templates? I’m not sure what exactly to copy in the GT_Sidebars. php or where to paste it to make a separate set. Can you expand on your instructions for this newbie?
    Thanks.

    • Gary says:

      Hi Paula,

      It’s just a case of making your styles a bit more specific. Lets say you’d added 2 sidebars in the traditional sidebar area set, and 3 for the footer area:

      require_once 'classes/GT_Sidebars.php';
      $traditionalsidebars = new GT_Sidebars(2, 'Traditional Sidebar');
      $traditionalsidebars->hook('thesis_hook_before_footer');
      $footersidebars = new GT_Sidebars(3, 'Footer Sidebar');
      $footersidebars->hook('thesis_hook_before_footer');

      The clue to know how to narrow the scope of your CSS, is by the name you’ve given them – in this case, “Traditional Sidebar” and “Footer Sidebar”.

      The default CSS I suggest just needs tweaking slightly to:

      .custom .sidebar div.widget_column {float:left;margin:5px 3px 0 0;padding-left:10px;text-align:left;}
      .custom .sidebar div.widget_column_1 {width:98%;}
      .custom .sidebar div.widget_column_2 {width:47%;}
      .custom .sidebar div.widget_column_3 {width:31%;}
      .custom .sidebar div.widget_column_4 {width:23%;}
      .custom div#traditional_sidebar_sidebar div.widget_column {width: 98%; float; none;}

      That final line (the only change from the styling suggested in the post), simply says “hey, if it’s a sidebar (widget_column) in the traditional sidebar set, then make sure the width fills the whole available space (and not just half of it), and that it’s not floated into a horizontal position” (you may find this float:none; can be omitted).

      In summary, no new templates should be needed – it can all be styled from within CSS – that’s the reason there’s so many elements with IDs and classes!

  10. Richard says:

    Help, I am getting this error message:

    Parse error: syntax error, unexpected T_LNUMBER in /home/thelang2/public_html/tufnell-park.com/wp-content/themes/thesis_17/custom/classes/GT_Sidebars.php on line 11

    What am I doing wrong?

    Thanks

    Richard

    • Gary says:

      Hi Richard,
      Assuming you’ve copied the main class file correctly, can you show me how you’ve included it in the custom_functions.php file, along with a few lines of code before and after it? I think the issue may be there, and not the class file itself.

      • Richard says:

        Gary

        I have now resolved the problem (not entirely sure how, but it worked). My custom_functions.php looks like this:

        hook(‘thesis_hook_before_footer’);
        }

        What I am really struggling with is how to implement it, i.e. make the leap to actually implementing the hook as I have never done this before. This was about as far as I got:

        add_action(‘thesis_hook_before_footer’,…..

        Guess I really need to go back to the drawing board on all this!

        Thanks

        Richard

        • Gary says:


          require_once 'classes/GT_Sidebars.php';
          $footersidebars = new GT_Sidebars(3, 'Footer Sidebar');
          $footersidebars->hook('thesis_hook_before_footer');

          …should be something like you needed. The usual “add_action(…)” line you’d need for attaching functions to events is built-in to the class file – we know what function it is (outputing the sidebar code), so all you need to provide is the hook to attach it to, which you do with the “->hook(…);” code.

  11. Richard says:

    Sorry my custom.function is thus:

    hook(‘thesis_hook_before_footer’);
    }

  12. Sean says:

    Maybe I misunderstood the tutorial, but why couldn’t you just use a plugin like widget logic and set a conditional tag on each sidebar item? Is there a benefit to using this method over that? Outside of having to use a plugin, of course.

    • Gary says:

      Some people detest using plugins – apart from anything, deciphering what a plugin is actually doing can be hard if you’re not a coder as it’s functionality it caught up in the Plugin and Widget APIs of WordPress. Performance is another reason some would prefer a non-plugin way to achieve what they require.

      In the class file here, while it maybe not 100% understandable by non-coders, it’s clear there’s no calls to the database that’s going to wipe years of posts, or add in spam links everywhere. It gives some people peace of mind that they can generally see what the code is before activating it on their precious site.

      Lastly – using the code above is vastly more flexible than something a plugin author can produce – the outputs can have different templates (although the default should be sufficient for most cases), which can either be written by the end-user if they are a coder, or any PHP writer; there’s no reliance on the plugin author to make global changes that affect all of their plugin users or having to hack the plugin with it then being at risk of accidentally updated and those changes overwritten.

  13. Raymond says:

    This is one of the most helpful tutorials for customizing Thesis I have yet to come across. Thank you SO much for sharing this info with the rest of us. It worked PERFECTLY. So far I’ve added a widget to appear “above_headline” in my post, which I am using now to place rotating ads. And I’ve added 2 “before_footer” widgets. Bottom one for more ads, and top one for a Fat Footer. This is so much easier to do than others tuts I have seen. Thanks again.

  14. Raymond says:

    Sadly, I can not get the Exclude condition working. I enter the page ID numbers I DO NOT want my “before_headline” widget to appear, but it is still there. Is there away instead of having to specify each and every page you want the sidebar Excluded, to tell it NOT to show up on PAGES, and only show up on POST?

    Thanks again. I may have to dump this sidebar if I can not get it to work correctly… :(

  15. Chris says:

    Finally, Thesis has become a whole lot easier to understand and design for. I’d almost given up on it but I kept returning due to the great SEO built in to the theme. Adding new sidebars seemed impossible but your code has sorted all that out. Many thanks for sharing this.

  16. Lori Corbett says:

    Hi Gary,
    I copied your php and pasted into notepad, saved as .txt, then renamed as .php
    Uploading into my new Thesis_18/custom/classes folder

    Copied into into my custom_function.php file the following:
    require_once ‘classes/GT_Sidebars.php’;
    $additionlWidgetSidebar = new GT_Sidebars(1, ‘Additional Widgets’);
    $additionlWidgetSidebar->hook(‘thesis_hook_before_sidebars’);

    Haven’t altered any code – just copy and pasted as-is. I get the following error:
    Parse error: syntax error, unexpected $end in /home/left/public_html/wp-content/themes/thesis_18b1/custom/classes/GT_Sidebars.php on line 223

    Line 223 on GT_Sidebars.php Is the very last curly brace ( } )
    What happened?
    thanks!
    L

    • Gary says:

      Difficult to say. I’ve not tried this code with Thesis 1.8.

      If you comment out (prefix the line with //) the 2nd and 3rd line (not the require_once line), does it still give the same error?

      • Lori Corbett says:

        Hi gary…thanks for your quick reply.
        I commented out the two lines and I get the same error message.
        It could very well be a thesis 1.8 issue.
        Oh well…off to plan B :-)
        Lori

  17. Gary,
    I am using Thesis 1.8 and having the exact same problem as Lori Corbett.
    Have you tried this in 1.8 yet? I would love to get this to work. Any suggestions? Thanks!

    • Gary says:

      Christine,
      No, I’m afraid I’ve not tried this with Thesis 1.8 as I’ve stopped using Thesis in favour of the Genesis Framework.
      As such, it’s highly unlikely I’ll go back and fix this up.

Speak Your Mind

*