8 Top Tips for Wordpress Theme development

Wordpress tips

Having moved this blogs CMS from ExpressionEngine to Wordpress 2.7 , I wanted to design and develop my own theme. You can start from blank canvas themes however I chose to start completely from scratch primarily so that I could get a good idea about how things work in Wordpress.

I did hit a few roadblocks during development and what follows are a few tip that could help you out if your creating your own theme.

Adding a body tag ID dynamically

There are times when it’s really useful to alter styling between pages using an ID on the body tag that can then be targeted via CSS. In Wordpress this get’s a little tricky as pages are repurposed like single.php. So I created a new function in my functions.php file to dynamically assign preset ID’s to selected pages.

function jmw_body_class( $print = true )
{
	global $wp_query;
	$c = "";
 
	// Generic semantic classes for what type of content is displayed
	is_archive()     	? $c = 'bpgArchive'    	: null;
	is_date()        	? $c = 'bpgDate'       	: null;
	is_search()      	? $c = 'bpgSearch'     	: null;
	is_paged()       	? $c = 'bpgPaged'      	: null;
	is_page()			? $c = 'bpgPage'		: null;
	is_page('Journal')	? $c = 'bpgJournal'		: null;
	is_page('About')	? $c = 'bpgAbout'		: null;
	is_page('Projects')	? $c = 'bpgProjects'	: null;
	is_page('Contact')	? $c = 'bpgContact'		: null;
	is_single()  	 	? $c = 'bpgPost' 		: null;
	in_category('4')	? $c = 'bpgJournal'		: null; //Single page for Journal entries
	in_category('11') || in_category('8') || in_category('10') ? $c = 'bpgProjects' : null;
	is_home()        	? $c = 'bpgHome'       	: null; // For the blog posts page, if set
	is_404()         	? $c = 'bpg404'     	: null; // CSS does not allow a digit as first character
 
	return $print ? print($c) : $c;
}

You would call this from your header.php template file like this:

<body id='<?php jmw_body_class(  ) ?>'>

The code should be clear, what we are doing is using Wordpress’s functions to determine what page is being called. The standard ones are there, then I have added my own specifically for this site. I have page files like Journal and Projects that I can identify using the is_page() function.

Watch the order of items. This is because is_single() will fire for every single page and as I have separate single pages depending upon the category of the post. So by adding an in_category() rule after is_single() I can target the singles page for those category posts.

Better SEO page titles

It’s always a good idea to have the best semantic page titles you can. For SEO purposes your title tag should be unique to each page, so you want to include things like the post title, what page you are on if your paging through archives and possibly your sites name.

I always place my site name at the end of any title, apparently this is better for the likes of Google but more importantly better for people bookmarking your page – the content is described first followed by your sites name.

So like the example above it’s into your functions.php file to add something similar to:

function jmw_page_title( )
{
	global $paged;
	$c = '';
 
	// is the current page a tag archive page?
	if (function_exists('is_tag') && is_tag()) 
	{ 
		// if so, display this custom title
		$c = 'Tag Archive for &quot;'.$tag.'&quot; - '; 
 
	// or, is the page an archive page?
	} elseif (is_archive()) { 
 
		// if so, display this custom title
		$c = 'Archive for '.wp_title('',false); 
 
	// or, is the page a search page?
	} elseif (is_search()) { 
 
		// if so, display this custom title
		$c = 'Search for &quot;'.wp_specialchars($s).'&quot; - '; 
 
	// or, is the page a single post or a literal page?
	} elseif (!(is_404()) && (is_single()) || (is_page())) { 
 
		$c = wp_title('',false); 
 
	// or, is the page an error page?
	} elseif (is_404()) {
 
	// yep, you guessed it
	$c = "opps, sorry I'm a 404 error page - "; 
 
	} elseif (is_home()) {
		$c = get_bloginfo('name') . ' - ' . get_bloginfo('description'); 
	} 
 
	//Shows what page your on
 
 
 
	if ( $paged >= 2 ) {	
	 	$c .= " page ". $paged;
	}	
 
	// finally, display the blog name for all page types
	if (!is_home()){	$c .= $pagenum .  ' &raquo; ' . get_bloginfo('name');}
 
	return print($c);
}

The just include the following PHP in your header.php file:

<title><?php jmw_page_title();?></title>

Take a look at the title’s on this site for an example of how this works.

Load category specific single post page

This is covered by many other Wordpress theme blogs. I wanted to have a differently structured page for my single project posts compared to my single journal posts. Wordpress will naturally open up single.php when asked to serve up a single post.

The key is to remove all content from the single.php page and include the appropriate single page depending upon the post category:

	<?php 
	// Journal entries
	if ( in_category('4') ) 
	{
		include(TEMPLATEPATH . '/single-journal.php');
	}
	//Projects
	elseif (in_category('11'))
	{	
		include(TEMPLATEPATH . '/single-projects.php');
	} 
	?>

This is small but the theory is that you can have differently structured pages for each category if you so wished. It’s worth saying that if you have the same page structure and you just wanted to load up different CSS just follow the same principle above.

Fixing the more tag

When it comes to limiting a posts output like on the homepage, you use a number of methods. There is the standard the_excerpt or the common the_excerpt_reloaded (plugin) or you could just use the more option. Many themes use the_excerpt_reloaded to limit content based upon character length and tags whilst still retaining valid XHTML tags. This didn’t work exactly how I wanted so I reverted back to using the more option in the Wordpress editor.

Problem was it was failing within some of my custom loops. So here is a fix that works:

<?php
	//Fix to get the more tag to work properly
	global $more;
	$more = 0;
	the_content(""); 
?>

Using additional stylesheets

As a good web developer you will no doubt have the need to include more than one style sheet into your theme. A standard Wordpress theme will have style.css in the theme folder root and you could use the @import rule in that CSS file to load extra style files for modern browsers. However you may want to include a print or handheld media stylesheet or even use IE conditional comments for loading in additional CSS.

Simple you just need to get the URL address path for your theme at runtime:

<link rel="stylesheet" type="text/css" media="print" href="<?php echo get_template_directory_uri(); ?>/styles/print.css" />

Target the first post in a list

Using the loop you can style or alter the markup for the first post (or any number in reality). This might be useful in your theme to allow more text or have a larger layout than the rest of the posts in alist.

This is easily done without using any plugins like this, add a new php variable before your loop code ($count in this example):

<?php query_posts('cat=1&showposts=5&order=DESC'); ?>
<?php $count = 1; ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

Now in your code for writing out the content you can use that new variable in a conditional, not forgetting to increase the counter afterwards:

<?php if ($count == 1) : ?>
	// You different code for the first post goes here
<?php else : ?>
	// If the count is greater than 1 then this will be used
<?php endif; $count++; ?>

Fixing broken paging links

Depending upon your permalink structure Wordpress (at least with version 2.7) can break your paging links at the bottom of a post. This solution worked although I could not get it to fully work when using a custom homepage. If you have any suggestions please leave them in the comments.

When calling your custom query pass through a page variable:

<?php query_posts('cat=4&posts_per_page=5&paged='.$paged); ?>

Wordpress security

SmashingMagazine.com recently had a great series of articles on how to make your Wordpress installation more secure. I have followed a number of these suggestions, they are well worth a look.

In following one of the suggestions to rename your table prefix from wp_ to something a little more obscure and random, I hit a bit of trouble. Basically this should ideally be done when you first install wordpress. However I had already start my Wordpress site so had to do it retrospectively.

Following this guide, I managed to change the database tables. However I could not log into the admin interface. To get around this you also need to change any values inside wp_options table, look for wp_user_roles and change the wp_ bit to your new table_prefix.

In conclusion

I have really enjoyed working with Wordpress on my site redevelopment. ExpressionEngine was becoming very clunky and is starting to show it’s age, the new EE2.0 has some tough competition. With some tweaking Wordpress is very capable as a CMS. It is not without it’s oddities and some of the UX in the admin area is a little questionable. But if you fancy rolling up your sleeves and getting dirty with a bit of PHP then you can achieve great things with Wordpress.

Posted in: journal | Tagged with: