Extra Info on Creating WordPress Themes
Anthony, over at Maddison Designs, happily reminded me this morning that I needed to update my tutorials on creating WordPress themes. He is such a sweetheart – he said he actually learned how to do it himself from a tutorial I wrote eons ago. I caught him in a discussion on Twitter with someone else, talking it over, and I realized exactly how old the tutorials were (the first is now over 6 years old, while the second run is over 3).
Yes, I should be updating these things more often, but honestly, I didn’t know so many people actually still read these things! So here I am, giving it another update.
The funny thing is, even as old as these tutorials are, they still apply. I wrote the original tutorial for WordPress 2.x – I can’t honestly even remember exactly which version it was, it was so long ago. (The top of the tutorial says it was for 2.0, but even so, I’m not even 100% sure it was exactly that version.) The second run was for 2.8. We’re now just starting to enjoy the loveliness that is 3.4.
Honestly, the second tutorial is quite a bit more comprehensive, and is closer to what I use today. There’s a few additions now – like the inc folder (which usually contains the widgets.php file), child themes, MultiSite, and custom post types/taxonomies. I really don’t want to go into all the old stuff, since it’ll just be re-hashing everything I’ve already written. But I’m more than happy to go over the new stuff.
Unfortunately, I haven’t had much of a chance to work with MultiSite. No opportunities have come my way on that end, so I’m going to have to regretfully pass on discussing that, since I simply don’t know enough about it yet. I only tried MultiSite once in my career, and the site I used it for ended up shutting it down within a few months (not because of the site, but because the business it was going to be used for shut down.) There wasn’t a whole lot I got to do with it, and it was long before you could simply activate MultiSite from a single installation with a line in wp-config.php. Someday, however, I will dive into it. (Maybe it’ll end up being the trend for 2013!)
inc/ folder and Widgets.php
I can go over the inc/widgets.php very quickly. Personally, I don’t use it. Most of the widgets I write are “general purpose”, meaning that if the client ends up changing the theme, I want them to continue using the widgets at hand, so I write a plugin instead. That way, the widgets remain, even if the theme changes. When you use the inc folder within the theme files, then as soon as you change the theme, the widgets go away (unless you write them/’port them over into the new theme).
Now, this is actually a good thing, if you’ve written custom widgets that are theme-specific. If you do, it’s pretty simple: simply open up your functions.php file and add this line to the top:
1 |
require( dirname( __FILE__ ) . '/inc/widgets.php' );
|
Pretty simple, eh? This is a nice little trick you can do, too, because if you have other code, etc. that you’d like to have better organized within your theme files, you can pretty much do this for anything. Just pop your file into the “inc” folder” and call it in – then you can WordPress it up
(This has come in really handy for when I did directory sites – I can put in all those directory-related files into the inc folder and not get them confused with the theme files.)
You certainly don’t want to try and “organize” your template files though, because doing so will mess with how things are displayed, since WordPress looks for the files in your theme first, and if it doesn’t find them, uses twenty eleven’s stuff instead. But for anything you want to add, it’s wonderful.
Child Themes
Child themes are pretty new to me, to be honest. Like MultiSite, they haven’t come across my path quite yet. I will share what I know, but I can’t promise to have a full understanding of them, and I won’t be providing full-on tutorials on them yet.
The very simplest explanation of a child theme is from the Codex:
A WordPress child theme is a theme that inherits the functionality of another theme, called the parent theme, and allows you to modify, or add to, the functionality of that parent theme.
Clear as mud, right? To me, it pretty much sounds like regular themes – where you can create a new file that corresponds to some page, category, archive, custom post type, what have you; and then write additional functions that you can plug into the inc folder, right? How are they any different from regular theme files?
The thing is, let’s say you bought a theme from theme forest or something. The theme is so very close to what you need, but there’s some functionality you have to have that the purchased theme does not provide. And what happens if you use that theme, make massive edits to it to customize it to your needs, and then it’s upgraded? Everything’s overwritten, and all of it’s gone (or you have to go back to your backup and re-import all your edits).
That’s where child themes shine: you can customize an existing theme and not worry about it getting overwritten. You can use the stuff thats’ there, and simply add to it to make it suit you, and not touch the regular theme files.
To create a child theme (of an existing parent), you simply have to make the addition of a single line in the style.css file of your child theme folder: “Template”. In the top of your style.css file, where you have to put in the theme name and decscription (so WordPress understands what it is and uses it), you just add in the “Template” links, and set the name of the directory of the parent theme.
So, for example, say I bought the “Slab Theme” from Theme Forest.(no, I have no affiliation with either of these – I just thought the thumbnail was pretty.) You put the theme in your WordPress “themes” folder. Create a new theme (with your standard files: stye.css, header.php. functions.php, footer.php, sidebar.php, and index.php) and in the top of the style.css file, you pop in:
1 |
Template: slab
|
in that commented-section. Bam, now you can use all the functionality and style of the slab theme, but customize the crap out of it.
In other words, instead of using Twenty Eleven as the default fallback, it’ll use Slab. With the added bonus of also allowing you to use all the functionality and styles of Slab without making specific callbacks to it – you just use them.
Hopefully that makes sense
Custom Post Types and Taxonomies
Now THIS is where I’ve been getting a lot of experience in. First off, I want to tell you that WP Alchemy (for meta boxes) and Advanced Custom Fields are two AMAZING plugins that will pretty much do anything you need.
However, the reason I’ve become so good at writing my own custom post types and taxonomies are because of the plugin writing I do. I don’t want any of my plugins to be dependent on someone else’s work, so I manually write them up myself.
Creating custom post types really isn’t that difficult. The Codex has an excellent explanation on how to pull it off, and I don’t think I could add to it to make it any better.
The trickiness in custom post types actually comes with just a couple of things- where I’ve had to sort it out with trial and error. Mostly it has to do with taxonomies (and displaying /querying them), but there’s a bit of an issue with the “query_var” and “rewrite” sections of creating a custom post type. The codex has gotten a lot better in explaining these two – because originally they were just boolean values. But if you just use boolean values, you kind of get some weird output.
‘query_var’ is to simply set the term you want to use when querying the custom post types. Like when you use query_posts to grab the “cats” category, you’ll want some term to query the custom post type. Now, by default (if you just set query_var to “true”) it’ll use the name you gave the custom post type when you registered it.
1 |
register_post_type('campaign_posts', array(
|
by default, the query variable is ‘campaign_posts’, so when using query_posts, you’d put in:
1 |
query_posts(array('post_type' => 'campaign_posts'));
|
But, if you set the ‘query_var’ to something else (say, “campaigns”) then you can
1 |
query_posts(array('post_type' => 'campaigns'));
|
And that will work, too.
I suppose it’s a bit pointless, because you can just register the post type as whatever you want to name it, but sometimes it comes in handy.
“Rewrite” confused me for the longest time (what can I say, I work a lot without coffee), because you can use either a string or a boolean value. “Rewrite” has to do with your permalinks. It looks like so:
1 |
'rewrite' => array( 'slug' => 'campaigns', 'with_front' => true ),
|
there’s a couple of other attributes you can pop in there, but these are the two you will use the most. Basically, “slug” is the slug you’ll see in the URL when you’re on a custom post type. “with_front” is whether or not you want the additional settings in your permalinks to show up, or make it look like it’s a Page. For example, if you have your custom structure as “/%category%/%postname%” (which means, when you’re in a category, you’ll have “/category/cats” in your permalink, when you’re in the “Cats” section), “with_front => true” will have your custom post type set up to show “/category/campaigns” in the URL. But if you have “with_front => false”, then it’ll just be “/campaigns”.
For the record, NEVER use a slash in the slug (i.e you want to give your custom post type a “custom front”). It’ll become a headbanging experience of epic proportions. BIG fat no-no. Take it from me – you don’t even want to try.
Campaign Taxonomies
Creating these are very similar to creating a post type. here, I’ll pop in a bit of code I used for a recent client:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
add_action( 'init', 'create_campaign_cats' );
function create_campaign_cats() {
register_taxonomy('campaign_category', array('campaign_posts'), array(
'labels' => array(
'name' => 'Campaign Categories',
'singular_name' => 'Campaign Category',
'search_items' => 'Search Campaign Categories',
'all_items' => 'All Campaign Categories',
'parent_item' => 'Parent Campaign Category',
'parent_item_colon' => 'Parent Campaign Category',
'edit_item' => 'Edit Campaign Category',
'update_item' => 'Update Campaign Category',
'add_new_item' => 'Add New Campaign Category',
'new_item_name' => 'New Campaign Category Name'
),
'hierarchical' => true,
'show_ui' => true,
'query_var' => 'campaign-category',
'has_archive' => true,
'rewrite' => array('slug' => 'campaign-category'))
);
}
|
The one you need to pay the most attention to are the “hierarchical” (and for the love of all things holy, be sure you spell that word correctly. You have no idea how many times this didn’t work for me because I swapped the “e” and the “i”.) and the first “array” in the “register_taxonomy” line.
“hierarchical” will determine if this taxonomy is like categories (“true”) or tags (“false”).
That first array tells this function what post types to add these custom taxonomies to. For more than one post type, just use a comma-separated value. I.e.:
1 |
register_taxonomy('campaign_category', array('campaign_posts', 'post', 'some_other_post_type'),
|
A TIP: you can actually forego the “add_action” call to register meta boxes and/or taxonomies for a particular custom post type. How so, you ask? In the “register_post-type” call, add in:
1 2 |
'register_meta_box_cb' => 'callback_function_name',
'taxonomies' = > 'callback_function_name'
|
I know this isn’t as comprehensive a tutorial as I’ve given in the past (as far as creating the themes go), but that’s because the basics still remain the same. There’s new stuff that can be used to make things even more super-powered, which I’ve touched on here. But really, with the new additions, I’ll be posting more specific tutorials on theming (for example, the membership stuff that I’ve been slowly adding in). I don’t know if you all have noticed, either, but I’ve added a new section here called “code snippets” where I’m popping in little juicy tidbits I find myself using quite often – and I think that will also help with some of the more extensive things you can do with WordPress
Comments
Why you have applied the call back function on ‘taxnomies’.
LOJO November 30, 2012 at 12:35 amAt the end? That’s just a tip I touched on – an alternative you can use for your taxonomies. So you can create custom post type specific categories from within the “register_post_type” function. You can read on it here: register_post_type, and scroll down to “taxonomies”.
Shelly December 3, 2012 at 1:58 pm