I agree with everything on this page, especially the minimization of theme options. I’m really excited to see people calming down about the whole theme-option bonanza, and realizing that a lot of stuff can be done naively or through an existing plugin. Goes a long well with what I wrote on Function.
Tag Archives: WordPress
Custom Write Panels Re-Redux
This is one of the topics I like to talk about. I’ve not only written about it once, but I followed that up about a year later. But, here I am again, with new thoughts on things, and a different perspective.
The Old Way
The first time I wrote about the panels, I suggested setting up an array of information, that would be used to create the actual box. Then each piece of information would be saved into the database. That was a pretty good solution. Then, the second time, I thought “Hey, why not just store everything one big serialized array” That would stop me from having to define each variable before I could use the meta box information. Well, that worked out for a while, but then I started seeing some faults. When you imported a WordPress database, all of your custom field information would be totally borked. I’m sure there was a way to properly re-import the arrays, but not with my current setup (I think…). So there was the fault in storing the information in an array in the database. There was also a fault in storing the fields in a huge array. It was bulky, limited, and didn’t allow for very expansive boxes.
A Semi-Fix for using an Array
To try and fix the limitations of creating the meta boxes via a huge array, I created a switch loop that would loop through and check for different types. I had a few generic ones like text, textarea, select, etc (the ones you see in most places). But then I also added a case for something called “custom.”
<?php break; case 'custom' : include_once( TEMPLATEPATH . $callback ); ?>
So what that allowed me to do was define the metabox as being “custom”, and then I could create any custom fields, group of fields, in the $callback file I defined. Okay… that kind of fixes it. But then I realized, why not just do everything like that? Why limit the other options as well.
The New Way
My new way ditches the array of boxes entirely, and saves each piece of information in a separate field (which is still easily accessible (more on that later)), and allows for completely custom meta boxes.
All of the code posted below will go in
functions.phpin your theme. Also, I’m not going to explain each section line by line. Most of the code is re-used from the previous tutorials, so go check those out if you are confused.
Defining the meta box
Let’s create a function where we can initiate and add our meta boxes. We are using add_meta_box. I won’t go over what each parameter means, because I went over it in the other tutorials, and the codex are very helpful.
/**
* Create custom meta boxes.
*
* @since 1.0.0
*/
function sf_create_meta_box()
{
add_meta_box(
'sf-meta-box-subtitle',
__( 'Subtitle', 'sf' ),
'sf_meta_box_subtitle',
'post',
'normal',
'high'
);
}
So that function will add a meta box that I’m going to use for a subtitle. Now we need to define the callback function that will be called (sf_meta_box_subtitle). Unlike the old way, we now are building the HTML structure by hand. It may seem like more work, but really it’s just a few lines.
function sf_meta_box_subtitle()
{
global $meta; sf_post_meta( $post->ID );
?>
<input type="text" name="sf_meta[subtitle]" value="<?php echo $meta[ 'subtitle' ]; ?>" style="width:99%;" /><br />
<p><?php _e( 'Use this to add a subtitle to the post.', 'sf' ); ?></p>
<?php
}
You’ll see a function in there, sf_post_meta that we haven’t gone over yet. That will be used to get the the meta information on the front-end, as well as the back-end. More on that later.
We need to now call the original function in the admin panel, so it knows to load in the meta boxes. A simple one-liner will do that:
add_action( 'admin_menu', 'sf_create_meta_box' );
Saving the Data
Now we need to save the data. First we do a few checks to see if we need to save the information. We don’t want to do anything if no data has been submitted, if a revision is being saved, or the current user can’t edit posts (someone being sneaky).
Next I added an action so if you ever need to do anything right before the meta information is saved (maybe add something more to the array), you can easily do that.
Because we have created an array of fields by using sf_meta[input_name], we can loop through those fields specifically. Then we just go through a few checks to see if we need to add, update, or delete the post meta.
And one final do_action so we can do anything extra if we need to afterwords.
/**
* Verify and save meta. Don't save if there is no specific meta, it is a revision,
* or the current user can't edit posts.
*/
function sf_save_meta_box( $post_id, $post )
{
global $post, $type;
$post = get_post( $post_id );
if( !isset( $_POST[ "sf_meta" ] ) )
return;
if( $post->post_type == 'revision' )
return;
if( !current_user_can( 'edit_post', $post_id ))
return;
$meta = apply_filters( 'sf_post_meta', $_POST[ "sf_meta" ] );
foreach( $meta as $key => $meta_box )
{
$key = 'meta_' . $key;
$curdata = $meta_box;
$olddata = get_post_meta( $post_id, $key, true );
if( $olddata == "" && $curdata != "" )
add_post_meta( $post_id, $key, $curdata );
elseif( $curdata != $olddata )
update_post_meta( $post_id, $key, $curdata, $olddata );
elseif( $curdata == "" )
delete_post_meta( $post_id, $key );
}
do_action( 'sf_saved_meta', $post );
}
add_action( 'save_post', 'sf_save_meta_box', 1, 2 );
Using the Data
I said before that it was a pain defining a variable for each field of meta information you wanted to use. Well it is. However, this time around I have a solution. The following function will do a few things: Define a post ID if one doesn’t exist (tries to get one from the loop), and gets a list of meta keys associated with that post.
Then here is where it gets cool: WordPress adds an underscore to all of their internal information. So we know we don’t need to grab any of that. So as we loop through, anything that starts with an _, we simply ignore. Otherwise, we add it to our $meta array. Then we cut out our prefixed meta_, and add just the simple part of the key to our array.
/**
* Gathers all meta objects attached to a certain posts.
* Excludes WordPress internal meta and creates an array of data.
*/
function sf_post_meta( $post_id = '' )
{
global $meta, $post, $wpdb;
if( empty( $post_id ) )
$post_id = $post->ID;
$meta = array();
$custom_field_keys = get_post_custom_keys( $post_id );
if( $custom_field_keys )
{
foreach( $custom_field_keys as $key => $value )
{
$valuet = trim( $value );
if ( '_' == $valuet{0} )
continue;
$value_short = str_replace( 'meta_', "", $valuet );
$meta[ $value_short ] = get_post_meta( $post_id, $value, true );
}
}
return $meta;
}
Now in our page, we can just do this after our while loop.
<?php while( have_posts() ) : the_post(); sf_post_meta(); ?>
Notice the call of sf_post_meta? That is what’s going to call all the meta info we need. Then we can just do the following when we need to access the data.
<div class="subtitle"><?php echo $meta[ 'subtitle' ]; ?></div>
If this does not work, try adding
global $meta;before the loop.
Conclusion
It’s as easy as that. Now you can create beautiful meta boxes that are integrated directly into the writing pages, without having to deal with clunky arrays, or worrying about defining a ton of variables to access your data.
WPBundle
This is the type of code that will be powering the themes on WPBundle. The code that will be behind these themes (HTML/PHP, excluding CSS), will be licensed under the GPL, which means that you will be able to freely use and access the code whether you have paid for the themes or not. (You will still need to buy the bundle to get the images, CSS, support, and PSD files.) I urge you to subscribe to WPBundle so you can stay up to date on all of the going-ons.
My WordPress Setup
I thought I’d give a quick overview of the extra stuff I’ve got running on this blog. Some plugins, features, and just some fun WordPress snippets that you can use on your own site.
It’s ironic, because I work with WordPress almost every day of the week, but this is my first personal blog I’ve had that runs on WordPress. I’ve used it for just about everything under the sun, except for just blogging. I’ve almost forgotten how great it is at it. I’ve customized all of my of the writing pages, only showing the panels that I need, creating a really clean and usable space. I usually spend so much time in the theme code that I hardly stop to look at how the admin section of WordPress functions. It’s amazing.
Current Plugins
- Hello Dolly – I added a random quote on the 404 Page
- Revision Control – to keep the database nice and tidy
- Short Post URLs – creates the pretty short URLs
- SyntaxHighlighter Evolved (styled) – to create awesome looking highlighted code boxes
- WP to Twitter (slightly modified) – to post all my new posts straight to Twitter
Theme Guts
As far as for the theme code, I’m running an alpha version of the theme framework I am developing for [tag]WPBundle[/tag]. Here are a few little functions I wrote to add some extra functionality to the theme.
How I Setup My Loop
I decided to only use tags, instead of categories. Since I don’t really have a set list of things I’m going to blog about, and I’ll be posting random links, excerpts, etc, I figured just being able to tag posts with what I wanted would be less limiting than categories.
I’m going to use a mix of categories and tags. Categories will define how the post is displayed, then I’ll tag it with some more useful things, making finding posts easier.
For the sake of posting code, here is how I setup my loop.php file. I modeled it after the new Twenty Ten theme.
<?php if( in_category( array( 'aside', 28 ) ) ) : ?> // The post layout for small excerpts <?php elseif( in_category( array( 'link', 34 ) ) ) : ?> // The post layout for links <?php else : ?> // The post layout for full articles <?php endif; ?>
Nothing special. I’ve just hard-coded in a few tags that I check for. If the post includes one of them, I use a certain post layout. Very simple and easy. Like I said, it’s the same as Twenty Ten, but I check for tags instead of categories.
Twitter URL Counter
Since I went through the effort of getting the nice pretty short(er) URLs, I figured it would be cool if I tracked them throughout Twitter. You’ll notice that if you hover the little Twitter birdie icon, the number of times the article has been tweeted appears. The little function below finds the number of times a URL has been tweeted.
/**
* Find out how many times the URL has been tweeted.
* The results will be underwhelming.
*
* @since 1.0.0
*/
function sf_tweeted_url( $url )
{
include_once( ABSPATH . WPINC . '/rss.php' );
$results = fetch_rss( 'http://search.twitter.com/search.atom?q=' . $url . '&rpp=50' );
$total = count( $results->items );
if( $total > 50 )
echo "50+";
else
echo $total;
}
About as simple as it can get. Include the RSS reader WordPress uses (Magpie), then fetch the RSS feed for the search results where the tweet contains the URL. I just fetch the first 50, and then if the results are less than or equal to 50, I echo the number. Otherwise, I show “50+” (it will never happen.)
Tag Link Generator
When writing a post, I figure the more things you can link to, the cooler. Or not. But I do think it’s helpful to easily be able to link to specific things throughout the site. I wanted a way to easily be able to link to a specific tag on the site. So I created a shortcode so I just have to do [tag]Spencer[/tag], and a link is automatically generated to all posts tagged with ‘Spencer’.
/**
* Creates a tag shortcode.
* Automatically links to the tag inside of it.
*
* @since 1.0.0
*/
function sf_shortcode_tag( $atts, $content = null )
{
return sprintf( '<a href="http://spencerfinnell.com/archive/tag/%s/">%s</a>', $content, $content );
}
add_shortcode( 'tag', 'sf_shortcode_tag' );
The URL could be a little more dynamic, but the that’s just one of the perks of coding for yourself.
Meta Boxes
I’m going to write a new post in a few days about the even newer way I create my meta boxes. It takes out all those nasty arrays, and just goes back to the basics. Typing out a few input fields by hand isn’t all that hard!
Press This
Press This is a bookmarklet: a little app that runs in your browser and lets you grab bits of the web.
This is the first time I’ve ever really looked into Press This, because like I mentioned before, I’ve never really been an…erm… “blogger“. Basically what it allows you to is add a bookmark link to your Bookmark toolbar (or folder) and when you click it, a window pops up that resembles the WordPress Add Post screen. However, it automatically fills out a few details, so you can quickly and effortlessly make a post.

I do have a small gripe with it though. Currently, there is no place add meta boxes. So for now, I had to do a little core hacking and insert a single line that would allow my meta boxes to be added the the bookmarklet.
Suggestions
Am I missing a plugin? Probably. I’m not an overly zealous plugin user, but if it servers a good function, I’m more than willing to try it out. Let me know if you have a sweet plugin I should check out.
#14164 (do_meta_boxes on press-this.php) – WordPress Trac
I created a ticket on Trac to try and get a patch in the core. It adds a do_meta_boxes call on pres-this.php so you can hook meta boxes into the bookmarklet (which I’m using right now.)
Spencer Finnell Blog—A Grand Illusion
Well, here I am on my first post, and I already don’t know what to talk about. This should be interesting. I give myself two weeks.
The main reason I built this was because I finished the design, and frankly, just like to code. It’s fun coding for yourself because you can implement whatever techniques you want, and you decide what how important you think IE is. (Not very important). I’ve implemented some pretty cool CSS3 techniques around the site, trying to use as few images as possible. The only images I used are icons, and grid pattern for the background, the rest of the things are rendered with CSS.
You can see the difference between Firefox and Internet Explorer in the image below:

The main differences are the lack of opacity and rounded corners in IE. It will be a very blocky experience for you IE people. However, I did make sure everything was functional. It works, but it’s not nearly as cool or pretty as in a real browser. I do realize there are people who have to use IE at work, etc, so there’s not getting around that. I will say, I never once looked at it in IE6 though. There are still some things I need to style, but I’ll just do that as they arise. I also will eventually make a better search results page. But for now, it works.
I also have a few little thing setup where I can post little excerpts, or asides in they will be a in different format than main articles. As well as similar functionality if I just want to post a link. Very tumblr-esq.
The site will mostly consist of [tag]WordPress[/tag] related stuff, with some [tag]tutorials[/tag], and the like.
I already feel like I’m talking to myself. So….