<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Justin Tadlock &#187; WordPress Tutorials</title>
	<atom:link href="http://justintadlock.com/tags/wordpress-tutorials/feed" rel="self" type="application/rss+xml" />
	<link>http://justintadlock.com</link>
	<description>Life, Blogging, and WordPress</description>
	<lastBuildDate>Wed, 01 Sep 2010 14:03:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Post types and taxonomies: Linking terms to a specific post</title>
		<link>http://justintadlock.com/archives/2010/08/20/linking-terms-to-a-specific-post</link>
		<comments>http://justintadlock.com/archives/2010/08/20/linking-terms-to-a-specific-post#comments</comments>
		<pubDate>Fri, 20 Aug 2010 14:05:53 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2525</guid>
		<description><![CDATA[When is something both a taxonomy term and post of a specific post type?  How do we handle that scenario in WordPress?]]></description>
			<content:encoded><![CDATA[<p>Almost every week I get asked a question about custom WordPress taxonomies and post types that has been bothering me for quite a while.  I&#8217;ve thought over several solutions to the question and haven&#8217;t necessarily found the perfect one, but I have found one that may work in some cases.</p>
<p>The question usually goes back to my original post on creating a <a href="http://justintadlock.com/archives/2009/06/04/using-custom-taxonomies-to-create-a-movie-database" title="Using custom taxonomies to create a movie database">movie database with taxonomies</a>.  In the tutorial, I explain how to make several taxonomies that represent people (actor, director, producer, and writer).  Taxonomies give us a way to clearly label and organize what roles a person takes on within the production of a movie.  The relationship between the given taxonomy and the movie post type usually stops there.</p>
<p>The question: <em>How does one make an &#8220;actor&#8221; both a taxonomy term and a post of a specific post type?</em></p>
<p>That&#8217;s essentially what most of the questions boil down to.  We want the clear organizational structure of taxonomies, but we also want each term in a taxonomy to behave as if it were a post/page with the ability to edit the content, upload media, have custom fields, and allow comments.  So, we also need a &#8220;person&#8221; post type to handle this.</p>
<p>Creating taxonomies and post types is the easy part.  Making the connection we want is the complex part of the question.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/08/taxonomy-to-post-type.png" alt="Taxonomy to post type" title="Making an object both a taxonomy and post type" /></p>
<h2>What we&#8217;re doing</h2>
<p>In this tutorial, we&#8217;re trying to make connections between two post types and one taxonomy.</p>
<ul>
<li>Movie (post type).</li>
<li>Person (post type).</li>
<li>Actor (taxonomy).</li>
</ul>
<p>In my movie database example, we&#8217;d be making the connection with several taxonomies.  But, I want to keep this tutorial simple.</p>
<p>The goal is to create a &#8220;movie&#8221; and list its actors on the movie page.  But, instead of going to an actor archive when clicking on one of the actor&#8217;s names, we want to visit a &#8220;person&#8221; page with custom content.  This would allow you to write custom content, upload images, add videos, open up the commenting section, and do all the things you&#8217;d normally be able to do with posts.</p>
<p>On the movie database, when we see Tom Hanks listed as an actor, we&#8217;d want to visit a <a href="http://popcritics.com/people/tom-hanks" title="Tom Hanks at Pop Critics">custom person page</a> we set up for him.</p>
<h2>Post type and taxonomy setup</h2>
<p class="alert">The rest of this tutorial assumes a working knowledge of creating post types and taxonomies.  The examples below will be limited and likely won&#8217;t be helpful unless you have an understanding of this process.  Please read my previous tutorials on <a href="http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress" title="Custom post types in WordPress">post types</a> and <a href="http://justintadlock.com/archives/2010/06/10/a-refresher-on-custom-taxonomies" title="A refresher on custom taxonomies">taxonomies</a> for a more in-depth review.</p>
<p>Open your theme&#8217;s <code>functions.php</code> file and add this <acronym title="Hypertext Preprocessor">PHP</acronym> code to create the movie and person post types.</p>
<pre><code>add_action( 'init', 'my_register_post_types' );

function my_register_post_types() {

	register_post_type(
		'movie',
		array(
			'public' => true,
			'labels' => array( 'name' => 'Movies', 'singular_name' => 'Movie' )
		)
	);

	register_post_type(
		'person',
		array(
			'public' => true,
			'labels' => array( 'name' => 'People', 'singular_name' => 'Person' )
		)
	);
}</code></pre>
<p>Now, let&#8217;s add some code for our actor taxonomy.</p>
<pre><code>add_action( 'init', 'my_register_taxonomies' );

function my_register_taxonomies() {

	register_taxonomy(
		'actor',
		array( 'movie' ),
		array(
			'public' => true,
			'labels' => array( 'name' => 'Actors', 'singular_name' => 'Actor' )
		)
	);
}</code></pre>
<p>That should give us a simple setup to work with and base to build our new functionality on.</p>
<p>The biggest thing to note here is that we have to be careful with our actor and person slugs.  When we create a new actor (term), we need to have the exact same slug as the person (post).  For example, when creating the Tom Hanks &#8220;actor,&#8221; it needs to have the slug of <code>tom-hanks</code>.  And, when we create the Tom Hanks &#8220;person,&#8221; it needs to have the slug of <code>tom-hanks</code>.  Otherwise, the proposed solutions below won&#8217;t work.</p>
<h2>Option #1: Changing term links to post permalinks</h2>
<p>One option is to change the links to actor archives to a specific post.  We&#8217;ll be working with term and post slugs in this step.  I normally don&#8217;t recommend using slugs because IDs are usually best to work with.  They don&#8217;t change and slugs can.  Unfortunately, connecting the terms and posts via ID isn&#8217;t something we can do right now.</p>
<p>The code below will do this step automatically for you.  What it does is filter <code>term_link</code> (link to actor archive page).  It grabs the term slug (actor name) and searches for a post slug that matches the term slug and has a post type of &#8220;person.&#8221;  If it finds the post, it switches the link for you.  Otherwise, it does nothing.</p>
<p>If you&#8217;re listing a ton of terms on one page, this solution isn&#8217;t ideal unless you mix it in with a caching solution.</p>
<pre><code>add_filter( 'term_link', 'my_term_to_type', 10, 3 );

function my_term_to_type( $link, $term, $taxonomy ) {

	if ( 'actor' == $taxonomy ) {
		$post_id = my_get_post_id_by_slug( $term->slug, 'person' );

		if ( !empty( $post_id ) )
			return get_permalink( $post_id );
	}

	return $link;
}

function my_get_post_id_by_slug( $slug, $post_type ) {
	global $wpdb;

	$slug = rawurlencode( urldecode( $slug ) );
	$slug = sanitize_title( basename( $slug ) );

	$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type = %s", $slug, $post_type ) );

	if ( is_array( $post_id ) )
		return $post_id[0];
	elseif ( !empty( $post_id ) );
		return $post_id;

	return false;
}</code></pre>
<h2>Option #2: Redirect term archives to posts</h2>
<p>In the above example, term archives are still publicly available.  We&#8217;re not doing a redirect, so it&#8217;s possible for someone to still stumble upon the archive or for you to even make it available if you wanted to.  But, if you&#8217;re looking for a way to redirect anyone that visits a term archive to the appropriate post, use the code below.  This method is also a lot more efficient.</p>
<p>Use this code in your <code>functions.php</code> file.</p>
<pre><code>add_action( 'template_redirect', 'my_redirect_term_to_post' );

function my_redirect_term_to_post() {
	global $wp_query;

	if ( is_tax() ) {
		$term = $wp_query->get_queried_object();

		if ( 'actor' == $term->taxonomy ) {
			$post_id = my_get_post_id_by_slug( $term->slug, 'person' );

			if ( !empty( $post_id ) )
				wp_redirect( get_permalink( $post_id ), 301 );
		}
	}
}

function my_get_post_id_by_slug( $slug, $post_type ) {
	global $wpdb;

	$slug = rawurlencode( urldecode( $slug ) );
	$slug = sanitize_title( basename( $slug ) );

	$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type = %s", $slug, $post_type ) );

	if ( is_array( $post_id ) )
		return $post_id[0];
	elseif ( !empty( $post_id ) );
		return $post_id;

	return false;
}</code></pre>
<h2>Asking for a term meta table</h2>
<p>There has been some discussion in the WordPress community about adding a <a href="http://core.trac.wordpress.org/ticket/10142" title="Add metadata support for taxonomies">term meta table</a> to the WordPress core.  I can list a ton of reasons this would be a great idea, but let me just focus on how it would make the above solutions even better.</p>
<p>Right now (in the examples), we&#8217;re calling up the database to search for a post based on a slug.  This isn&#8217;t something I really like to do on the front end, especially with the first example.  For example, listing 50 actors on a page using the first option would cause us to search the database 50 times to see if a post slug matches the taxonomy term.</p>
<p>A term meta table would easily solve this problem.  We could save the post ID as metadata for individual terms.  We could even do the post lookup in the backend instead of doing it on-the-fly on the front end of the site.  Or, even provide a nice interface for easily selecting the post/term we want to connect.  Having term meta would allow us to do a quick check if there&#8217;s a post we want to redirect to.</p>
<h2>Other solutions and thoughts</h2>
<p>The above solutions are just something I was tinkering around with because of the enormous number of questions I get about this.  I haven&#8217;t fully explored every possible option, so I can&#8217;t say that either is the best route to take.  Think of it more as &#8220;Justin thinking out loud&#8221; than a definite solution.</p>
<p>I would love to hear your take on other solutions or even solutions that we could try to get rolled into core to better handle metadata and relationships between post types and taxonomies.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/08/20/linking-terms-to-a-specific-post/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Linking post published dates to their archives</title>
		<link>http://justintadlock.com/archives/2010/08/06/linking-post-published-dates-to-their-archives</link>
		<comments>http://justintadlock.com/archives/2010/08/06/linking-post-published-dates-to-their-archives#comments</comments>
		<pubDate>Sat, 07 Aug 2010 04:39:22 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2507</guid>
		<description><![CDATA[Giving the post published date/time on WordPress a purpose by linking its individual parts to date-based archives.]]></description>
			<content:encoded><![CDATA[<p>I was just thinking the other day that date-based archives in most WordPress blogs don&#8217;t get enough exposure unless the blog owner uses a widget to show a list of archives.  Since I&#8217;m not a big fan of using long lists of archives in the sidebar and wasting valuable space, this method was out of the question for me.  </p>
<p>But, I still wanted a way to easily allow readers to visit my archives.  I also wanted to not just show monthly archives like the standard WordPress archives widget.  The method I decided on has three major benefits:</p>
<ul>
<li>Allows readers to find archives by year, month, and day.</li>
<li>Doesn&#8217;t take up any extra space on my blog.</li>
<li>The code was already written in my <a href="http://justintadlock.com/archives/2009/04/05/breadcrumb-trail-wordpress-plugin" title="Breadcrumb Trail WordPress plugin">Breadrumb Trail plugin</a>, so there wasn&#8217;t much I had to do.</li>
</ul>
<p>On this blog and many others, we have a thing called a <em>byline</em> or <em>dateline</em>, which is usually located before or after the post title.  Traditionally, the date the post was written is shown.  But, it doesn&#8217;t do much.  It just sits there.  Yes, it provides valuable information to the user but not anything more than that.</p>
<p>What we&#8217;re going to do is link the various parts of the date to archive pages.  We&#8217;re going to give the post date more purpose.</p>
<h2>Creating the post date link function</h2>
<p>The first thing we need to do is create a function in our theme&#8217;s <code>functions.php</code> file.  Actually, we&#8217;re going to create a function and a shortcode.  Just drop this <acronym title="Hypertext Preprocessor">PHP</acronym> code in the file:</p>
<pre><code>&lt;?php

add_shortcode( 'entry-link-published', 'my_entry_published_link' );

function my_entry_published_link() {

	/* Get the year, month, and day of the current post. */
	$year = get_the_time( 'Y' );
	$month = get_the_time( 'm' );
	$day = get_the_time( 'd' );
	$out = '';

	/* Add a link to the monthly archive. */
	$out .= '&lt;a href="' . get_month_link( $year, $month ) . '" title="Archive for ' . esc_attr( get_the_time( 'F Y' ) ) . '">' . get_the_time( 'F' ) . '&lt;/a>';

	/* Add a link to the daily archive. */
	$out .= ' &lt;a href="' . get_day_link( $year, $month, $day ) . '" title="Archive for ' . esc_attr( get_the_time( 'F d, Y' ) ) . '">' . $day . '&lt;/a>';

	/* Add a link to the yearly archive. */
	$out .= ', &lt;a href="' . get_year_link( $year ) . '" title="Archive for ' . esc_attr( $year ) . '">' . $year . '&lt;/a>';

	return $out;
}

?></code></pre>
<p>For non-American users, you might want to switch the dates around as I&#8217;m using the &#8220;Month Day, Year&#8221; format.  The WordPress Codex also has a helpful guide on <a href="http://codex.wordpress.org/Formatting_Date_and_Time" title="WordPress Codex: Formatting date and time">formatting date and time</a> if you want to mix things up a bit.</p>
<p class="alert"><strong>Note to theme authors:</strong>  Please don&#8217;t implement this function as is into your themes.  There are tons of variations on the date/time format and we have to respect what the user chooses unless the design can&#8217;t be accomplished without a specific format.  If you come up with a way to handle all scenarios, then by all means, go for it.</p>
<h2>Using the published link in your theme</h2>
<p>We&#8217;ve added the function to run this to our theme&#8217;s <code>functions.php</code> file.  Now, we have to use the function in our theme.  All themes are going to be a little different, so I can&#8217;t tell you exactly where to put the code.  You&#8217;ll just have to look in your theme templates or ask your theme author how to do it.  I can tell you that this code should go within The Loop.</p>
<p>This is the code you add to the template:</p>
<pre><code>&lt;?php echo my_entry_published_link(); ?></code></pre>
<p>That&#8217;s all the code you have to deal with.</p>
<p>If you&#8217;re using a super-intelligent theme like <a href="http://themehybrid.com/themes/hybrid" title="Hybrid WordPress theme">Hybrid</a>, you can use the <code>&#091;entry-link-published&#093;</code> shortcode and not worry about adding the <acronym title="Hypertext Preprocessor">PHP</acronym> function.</p>
<p>Or, if you&#8217;re not using Hybrid and just want to know how to run a shortcode in a theme template, try this out:</p>
<pre><code>&lt;?php echo do_shortcode( '&#091;entry-link-published&#093;' ); ?></code></pre>
<h2>What are the benefits of doing this?</h2>
<p>I count two main benefits:</p>
<ul>
<li>Providing an easy way for readers to visit your archives.  It never hurts to implement more methods of keeping people on your site.</li>
<li>It&#8217;s just something fun to do.  Maybe spruce up your blog a little.</li>
</ul>
<p>Maybe it&#8217;ll even help search engines crawl your site easier.  I don&#8217;t know.  I quit trying to figure them out a long time ago.</p>
<p>I hope you enjoy this little snippet of code.  If you want to see it in action, I&#8217;m using it on my blog now.  Just look at my post byline and you&#8217;ll see the date linked to three different archives.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/08/06/linking-post-published-dates-to-their-archives/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Meta capabilities for custom post types</title>
		<link>http://justintadlock.com/archives/2010/07/10/meta-capabilities-for-custom-post-types</link>
		<comments>http://justintadlock.com/archives/2010/07/10/meta-capabilities-for-custom-post-types#comments</comments>
		<pubDate>Sat, 10 Jul 2010 07:46:19 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2462</guid>
		<description><![CDATA[How to map meta capabilities for editing, deleting, and reading custom post types in WordPress.]]></description>
			<content:encoded><![CDATA[<p>While I was fiddling around with a new plugin that uses custom post types for WordPress the other day, I ran into a small issue that I hadn&#8217;t noticed before.  Meta capabilities for custom post types were not being automatically mapped, so I couldn&#8217;t have granular control over permissions.</p>
<p>At first, I was a bit disappointed that this wasn&#8217;t taken care of because this would be a major blow to my plugin.  However, I soon learned this could be considered a great feature rather than a bug.  </p>
<p><a href="http://andrewnacin.com" title="Andrew Nacin">Andrew Nacin</a> mentioned that we&#8217;d need to &#8220;<a href="http://core.trac.wordpress.org/ticket/14122#comment:1" title="Custom 'capabilities' appears broken on custom post types">roll our own handling</a>&#8221; for capabilities using the <code>map_meta_cap</code> hook.  This hook gives you control over the meta capabilities as well as the power to step outside of the WordPress way of doing things.  The more I play around with it, the more I&#8217;d rather WordPress <em>not</em> automatically map these.</p>
<p class="alert">Before reading on, please note that this is only an issue/feature if you&#8217;re using custom capabilities for your post types.  If not, this might not interest you much.</p>
<h2>What are meta capabilities?</h2>
<p>Meta capabilities are capabilities a user is granted on a per-post basis.  The three we&#8217;re dealing with here are:</p>
<ul>
<li><code>edit_post</code></li>
<li><code>delete_post</code></li>
<li><code>read_post</code></li>
</ul>
<p>For regular blog posts, WordPress &#8220;maps&#8221; these to specific capabilities granted to user roles.  For example, a user might be given the <code>edit_post</code> capability for post 100 if they are the post author or have the <code>edit_others_posts</code> capability.</p>
<p>When using custom post types, this mapping doesn&#8217;t happen automatically if you&#8217;re setting up custom capabilities.  We have to come up with our own solution.</p>
<p>In this tutorial, I&#8217;ll be using the <code>movie</code> post type, so the above three meta capabilities for our purposes will be:</p>
<ul>
<li><code>edit_movie</code></li>
<li><code>delete_movie</code></li>
<li><code>read_movie</code></li>
</ul>
<h2>Setting up your custom post type</h2>
<p>At this point, I&#8217;ll assume you&#8217;re familiar with creating custom post types.  If not, you&#8217;ll want to read through my <a href="http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress" title="Custom post types in WordPress">detailed tutorial</a> on them.  The code presented below will be an abridged version of what you might use.</p>
<p>We&#8217;re going to focus on two arguments, <code>capability_type</code> and <code>capabilities</code>.  These control the permissions for what a user with a specific role can do with the post type.</p>
<p>As mentioned earlier, the post type we&#8217;re going with is <code>movie</code>.  So, let&#8217;s set up that post type:</p>
<pre><code>add_action( 'init', 'create_my_post_types' );

function create_my_post_types() {
	register_post_type(
		'movie',
		array(
			'public' => true,
			'capability_type' => 'movie',
			'capabilities' => array(
				'publish_posts' => 'publish_movies',
				'edit_posts' => 'edit_movies',
				'edit_others_posts' => 'edit_others_movies',
				'delete_posts' => 'delete_movies',
				'delete_others_posts' => 'delete_others_movies',
				'read_private_posts' => 'read_private_movies',
				'edit_post' => 'edit_movie',
				'delete_post' => 'delete_movie',
				'read_post' => 'read_movie',
			),
		)
	);
}</code></pre>
<p>I&#8217;ve also added in a couple of extra capabilities that were not shown in my previous tutorial on post types: <code>delete_posts</code> and <code>delete_others_posts</code>.  We&#8217;re going to use these to give people the ability to delete posts (movies).</p>
<h2>Assigning capabilities to roles</h2>
<p>To assign specific capabilities to roles, you&#8217;re going to need a role management plugin.  A good one to use is my <a href="http://wordpress.org/extend/plugins/members" title="Members WordPress plugin">Members plugin</a>.  You could code this if you wanted, but it&#8217;s a bit outside the scope of this tutorial.</p>
<p>What you need to do at this point is assign capabilities to the roles that should have them.  Just be careful not to give too much power to the wrong roles.</p>
<ul>
<li><code>publish_movies</code>: This allows a user to publish a movie.</li>
<li><code>edit_movies</code>: Allows editing of the user&#8217;s own movies but does not grant publishing permission.</li>
<li><code>edit_others_movies</code>: Allows the user to edit everyone else&#8217;s movies but not publish.</li>
<li><code>delete_movies</code>: Grants the ability to delete movies written by that user but not others&#8217; movies.</li>
<li><code>delete_others_movies</code>:  Capability to edit movies written by other users.</li>
<li><code>read_private_movies</code>:  Allows users to read private movies.</li>
<li><code>edit_movie</code>: Meta capability assigned by WordPress.  Do not give to any role.</li>
<li><code>delete_movie</code>: Meta capability assigned by WordPress.  Do not give to any role.</li>
<li><code>read_movie</code>: Meta capability assigned by WordPress.  Do not give to any role.</li>
</ul>
<p>Just to say it again:  it is important that you don&#8217;t assign those last three capabilities to any role.  These are our meta capabilities that we&#8217;ll be mapping in the next section.</p>
<h2>Mapping the meta capabilities</h2>
<p>This part is completely customizable.  What we&#8217;re doing here is filtering the <code>map_meta_cap</code> hook so we can do our own mapping.  What this means is that users will be granted meta capabilities on a per-post basis so they can do things like edit their own posts.</p>
<p>I&#8217;m going to keep it extremely simple and follow my notes from the previous section.  If you wanted, you could do all kinds of crazy things here.</p>
<p>You can simply drop the below in your plugin or theme&#8217;s <code>functions.php</code> (whichever you&#8217;re using) and be done with it.  It&#8217;ll follow the rules I set forth above.</p>
<pre><code>add_filter( 'map_meta_cap', 'my_map_meta_cap', 10, 4 );

function my_map_meta_cap( $caps, $cap, $user_id, $args ) {

	/* If editing, deleting, or reading a movie, get the post and post type object. */
	if ( 'edit_movie' == $cap || 'delete_movie' == $cap || 'read_movie' == $cap ) {
		$post = get_post( $args[0] );
		$post_type = get_post_type_object( $post->post_type );

		/* Set an empty array for the caps. */
		$caps = array();
	}

	/* If editing a movie, assign the required capability. */
	if ( 'edit_movie' == $cap ) {
		if ( $user_id == $post->post_author )
			$caps[] = $post_type->cap->edit_posts;
		else
			$caps[] = $post_type->cap->edit_others_posts;
	}

	/* If deleting a movie, assign the required capability. */
	elseif ( 'delete_movie' == $cap ) {
		if ( $user_id == $post->post_author )
			$caps[] = $post_type->cap->delete_posts;
		else
			$caps[] = $post_type->cap->delete_others_posts;
	}

	/* If reading a private movie, assign the required capability. */
	elseif ( 'read_movie' == $cap ) {

		if ( 'private' != $post->post_status )
			$caps[] = 'read';
		elseif ( $user_id == $post->post_author )
			$caps[] = 'read';
		else
			$caps[] = $post_type->cap->read_private_posts;
	}

	/* Return the capabilities required by the user. */
	return $caps;
}</code></pre>
<h2>Now taking questions</h2>
<p>I realize there&#8217;s still quite a few things that I might not have covered in my tutorials on post types so far.  Some people have probably figured these out by now, but others of you may be stuck.</p>
<p>Feel free to ask any questions you have about post types, and I&#8217;ll see about answering them or writing more tutorials based on your suggestions.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/07/10/meta-capabilities-for-custom-post-types/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>A refresher on custom taxonomies</title>
		<link>http://justintadlock.com/archives/2010/06/10/a-refresher-on-custom-taxonomies</link>
		<comments>http://justintadlock.com/archives/2010/06/10/a-refresher-on-custom-taxonomies#comments</comments>
		<pubDate>Thu, 10 Jun 2010 08:26:16 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2432</guid>
		<description><![CDATA[Custom taxonomies in WordPress 3.0 are being updated to allow for more control and to give us options we've been waiting nearly a year for.]]></description>
			<content:encoded><![CDATA[<p>When I wrote about <a href="http://justintadlock.com/archives/2009/05/06/custom-taxonomies-in-wordpress-28" title="Custom taxonomies in WordPress 2.8">custom taxonomies</a> just a year ago, not much was known or understood about them in the WordPress community.  For most people, anything beyond &#8220;tags&#8221; and &#8220;categories&#8221; was unneeded anyway.  And, only having only taxonomies for blog posts was essentially useless.</p>
<p>However, with WordPress 3.0 around the corner and the introduction of <a href="http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress" title="Custom post types in WordPress">custom post types</a>, the usefulness of custom taxonomies will increase greatly.</p>
<p>Post types are your forms of content.  Taxonomies are the glue that holds that content together, linking it in all kinds of neat ways.</p>
<p>As I delve deeper into the subject of post types and taxonomies in this series of posts, I&#8217;ll give more examples of how these two things are related and how they can be used to create any type of site you want with WordPress.</p>
<p>First, we need a primer on taxonomies.</p>
<p>In WordPress 3.0, taxonomies will be super-charged.  While I do encourage you to go back and read my original post on <a href="http://justintadlock.com/archives/2009/05/06/custom-taxonomies-in-wordpress-28" title="Custom taxonomies in WordPress 2.8">custom taxonomies</a> and my followup on how I created a <a href="http://justintadlock.com/archives/2009/06/04/using-custom-taxonomies-to-create-a-movie-database" title="Using custom taxonomies to create a movie database">movie database</a> to gain a better understanding of taxonomies, I&#8217;ll try to cover the important details in this post.</p>
<h2>A refresher on what taxonomies are</h2>
<p>Taxonomies are a method for grouping content.  They&#8217;re a way of intelligently creating an organizational system for data.  Some examples include:</p>
<ul>
<li>Finding actors (taxonomy) that have played in specific movies (content).</li>
<li>Listing musicians (taxonomy) that have performed on various albums (content).</li>
<li>Locating restaurants (content) that serve specific types of food (taxonomy).</li>
<li>Getting recipes (content) that use certain ingredients (taxonomy).</li>
<li>Searching for jobs (content) in different fields (taxonomy).</li>
<li>Visiting a forum (taxonomy) that lists forum topics (content).</li>
<li>Scanning for books (content) written by your favorite author (taxonomy).</li>
</ul>
<p>Grouping content in this way simply isn&#8217;t possible with standard tags and categories.  To understand the benefits of taxonomies, you have to open your mind to possibilities beyond a standard blog. </p>
<h2>What&#8217;s new with taxonomies in 3.0?</h2>
<p>Some things have changed since the major overhaul in WordPress 2.8 of taxonomies.  Don&#8217;t worry; your previously-created taxonomies will still work fine.  But, now you have much more control.</p>
<p>The biggest changes are:</p>
<ul>
<li>Ability to create taxonomies for any post type (not just posts).</li>
<li>Hierarchical taxonomies now get admin screens just like non-hierarchical ones.</li>
<li>Control over the capabilities for editing, creating, deleting, and assigning terms.</li>
<li>Control over admin text for making the <acronym title="User Interface">UI</acronym> not seem so weird.</li>
</ul>
<h2>The register_taxonomy function</h2>
<p>To register a taxonomy, we must use the <code>register_taxonomy()</code> WordPress function.  It takes in three parameters.</p>
<pre><code>register_taxonomy( $taxonomy, $objects, $arguments )</code></pre>
<h4>$taxonomy</h4>
<p>The <code>$taxonomy</code> parameter should be a unique name for your taxonomy that&#8217;s not used by any other taxonomy.</p>
<pre><code>register_taxonomy( 'division', $objects, $arguments )</code></pre>
<h4>$objects</h4>
<p>The <code>$objects</code> parameter can be a string (single object type) or an array (multiple object types).  This represents the post types that you want to register your taxonomy for.</p>
<pre><code>register_taxonomy( $taxonomy, array( 'post', 'page' ), $arguments )</code></pre>
<h4>$arguments</h4>
<p>The <code>$arguments</code> parameter is an array of arguments that help define how your taxonomy should function.  I&#8217;ll cover these in more depth later.</p>
<pre><code>register_taxonomy( $taxonomy, $objects, array() )</code></pre>
<h2>Creating a custom taxonomy</h2>
<p>We&#8217;re going to keep everything pretty basic for this tutorial.  Let&#8217;s create a taxonomy called <code>division</code> for your blog posts.  The easiest way to do this is to add this code to your theme&#8217;s <code>functions.php</code> file or a plugin file.</p>
<pre><code>add_action( 'init', 'register_my_taxonomies', 0 );

function register_my_taxonomies() {

	register_taxonomy(
		'division',
		array( 'post' ),
		array(
			'public' => true,
			'labels' => array(
				'name' => __( 'Divisions' ),
				'singular_name' => __( 'Division' )
			),
		)
	);
}</code></pre>
<p>This will create a new item called &#8220;Divisions&#8221; for you under your &#8220;Posts&#8221; menu item in the admin.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/06/new-taxonomy.png" alt="Taxonomy screen in WordPress" title="Custom taxonomy admin screen in WordPress" class="aligncenter" /></p>
<h2>Controlling your taxonomy</h2>
<p>The arguments array (third parameter) of <code>register_taxonomy()</code> is the parameter that gives you fine-grain control over how your taxonomy functions in WordPress.  It allows for about 10 arguments, which I&#8217;ll cover in detail here.  In each section, I&#8217;ll give a basic code example of how each is used.</p>
<h4>public</h4>
<p>The <code>public</code> argument is sort of a catchall argument that controls whether your taxonomy is publicly used on the site or if works behind the scenes.  Depending on whether it&#8217;s set to <code>true</code> or <code>false</code>, it&#8217;ll automatically set other arguments if they aren&#8217;t defined.</p>
<ul>
<li><code>show_ui</code>: Whether the taxonomy should be shown in the administration interface.</li>
<li><code>show_tagcloud</code>: Whether to allow the taxonomy to be chosen in the tag cloud widget.</li>
<li><code>show_in_nav_menus</code>: Whether to allow terms from the taxonomy in navigation menus.</li>
</ul>
<pre><code>'public' => true,
'show_ui' => true,
'show_tagcloud' => true,
'show_in_nav_menus' => true,</code></pre>
<h4>hierarchical</h4>
<p>The <code>hierarchical</code> argument decides if your taxonomy&#8217;s terms are in a non-hierarchical (flat) or hierarchical format.  By default, this is set to <code>false</code>, so the taxonomy will behave like the post tag taxonomy.  Hierarchical taxonomies will behave like the category taxonomy.</p>
<pre><code>'hierarchical' => false,</code></pre>
<h4>capabilities</h4>
<p>New in WordPress 3.0 is the ability to change the capabilities for who can use the taxonomy in the admin.  By default, users of roles with the <code>manage_categories</code> capability can manage, edit, and delete terms, and those of roles with the <code>edit_posts</code> capability can assign terms to a &#8220;post.&#8221;</p>
<ul>
<li><code>manage_terms</code>: Ability to view terms in the administration. I don&#8217;t see any other use for this.</li>
<li><code>edit_terms</code>: Grants the ability to edit and create terms.</li>
<li><code>delete_terms</code>: Gives permission to delete terms from the taxonomy.</li>
<li><code>assign_terms</code>: Capability for assigning terms in the new/edit post screen.</li>
</ul>
<p>If you&#8217;re using a role management plugin like <a href="http://justintadlock.com/archives/2009/09/17/members-wordpress-plugin" title="Members WordPress plugin">Members</a>, you can assign which users have control over your terms.  If not, I suggest not changing these capabilities.</p>
<pre><code>'capabilities' => array(
	'manage_terms' => 'manage_divisions',
	'edit_terms' => 'edit_divisions',
	'delete_terms' => 'delete_divisions',
	'assign_terms' => 'assign_divisions'
),</code></pre>
<h4>labels</h4>
<p>The <code>labels</code> array is a set of text strings that control how your taxonomy is viewed in the admin.  If your taxonomy is non-hierarchical, this defaults to the post tag wording.  If it is hierarchical, it defaults to the category terminology.</p>
<ul>
<li><code>name</code>: The plural name that represents your taxonomy.</li>
<li><code>singular_name</code>: The singular name for your taxonomy.</li>
<li><code>search_items</code>: Text for the search button when searching the taxonomy terms.</li>
<li><code>popular_items</code>: Header for the popular cloud of terms (not used with hierarchical taxonomies).</li>
<li><code>all_items</code>: Text to display all of the terms of the taxonomy.</li>
<li><code>parent_item</code>: Text for displaying the parent term (not used with non-hierarchical taxonomies).</li>
<li><code>parent_item_colon</code>: Text for displaying the parent term followed by a colon (not used with non-hierarchical taxonomies).</li>
<li><code>edit_item</code>: Represents the text when editing a term.</li>
<li><code>update_item</code>: Displayed when updating a term.</li>
<li><code>add_new_item</code>: Text to display for adding a new term.</li>
<li><code>new_item_name</code>: Text to display for adding a new term name.</li>
</ul>
<pre><code>'labels' => array(
	'name' => __( 'Divisions' ),
	'singular_name' => __( 'Division' ),
	'search_items' => __( 'Search Divisions' ),
	'popular_items' => __( 'Popular Divisions' ),
	'all_items' => __( 'All Divisions' ),
	'parent_item' => __( 'Parent Division' ),
	'parent_item_colon' => __( 'Parent Division:' ),
	'edit_item' => __( 'Edit Divison' ),
	'update_item' => __( 'Update Division' ),
	'add_new_item' => __( 'Add New Division' ),
	'new_item_name' => __( 'New Division Name' ),
),</code></pre>
<h4>query_var</h4>
<p>The <code>query_var</code> argument allows you to get posts based on particular terms of the taxonomy through a query string in the browser URL bar or through a WordPress function like <code>query_posts()</code> or class like <code>WP_Query</code>.  This will default to the name of your taxonomy, but you can also set it to <code>false</code> to prevent queries.</p>
<pre><code>'query_var' => 'division',</code></pre>
<h4>rewrite</h4>
<p>The <code>rewrite</code> argument gives you control over the permalink structure of your taxonomy&#8217;s term archives.  You may want a structure like <code>yoursite.com/divisions/blue-group</code>, and this argument will give you control over that.  It can be set to true, false, or an array of values.  The values of the array are:</p>
<ul>
<li><code>slug</code>: The slug you want to prefix your term archives with.</li>
<li><code>with_front</code>: Whether your term archives should use the front base from your permalinks settings.</li>
</ul>
<pre><code>'rewrite' => array( 'slug' => 'divisions', 'with_front' => false ),</code></pre>
<h4>update_count_callback</h4>
<p><code>update_count_callback</code> allows you to write a custom function that will be called when the term count is updated.  Most users shouldn&#8217;t need this and shouldn&#8217;t bother setting this.</p>
<pre><code>'update_count_callback' => 'my_custom_count_callback',</code></pre>
<h2>To answer the 18 billion questions from the last year</h2>
<p>Since I first published an article on taxonomies last year, I&#8217;ve gotten numerous questions on using them.  The two questions that crop up the most:</p>
<ul>
<li>Can I create a hierarchical taxonomy like categories?</li>
<li>Can I use my taxonomy with pages (or other post types)?</li>
</ul>
<p>It&#8217;s been a long time coming, but I can finally say, &#8220;Yes!  And.  Yes!&#8221;</p>
<p>I didn&#8217;t want to overwhelm everyone with too much information in this tutorial.  I mostly wanted to give a refresher on taxonomies and cover some of the new features.  I encourage you to read my previous posts on the subject for a deeper understanding of taxonomies.</p>
<p>The problem I see now is that there&#8217;s one more question that needs answering &mdash; how to merge taxonomies and post types.  I&#8217;ve touched on this a bit in this post, but you can expect a real-world example from me in the near future.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/06/10/a-refresher-on-custom-taxonomies/feed</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
		<item>
		<title>Goodbye, headaches.  Hello, menus!</title>
		<link>http://justintadlock.com/archives/2010/06/01/goodbye-headaches-hello-menus</link>
		<comments>http://justintadlock.com/archives/2010/06/01/goodbye-headaches-hello-menus#comments</comments>
		<pubDate>Tue, 01 Jun 2010 10:44:53 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2413</guid>
		<description><![CDATA[WordPress 3.0 will introduce a new navigation menu system. This tutorial will walk you through using it from the admin and integrating it into your theme.]]></description>
			<content:encoded><![CDATA[<p>As a theme developer, most of the support questions I get are about configuring menus.  If you&#8217;re also a theme developer, you have probably run into the same questions I have.</p>
<p>The trouble is that a large majority of users want custom menus and no two menus are the same.  There are tons of plugins that <em>fix</em> this problem in their own way.  Even some theme developers have integrated menus systems into their themes.</p>
<p>Unfortunately, all of these solutions are different.  We haven&#8217;t had a standard to go by, at least until now.  WordPress 3.0 will introduce a new navigation menu system.  Sure, there are some limitations with this system.  However, with a set standard, new plugins will likely emerge to fill in the gaps.</p>
<p>In this tutorial, I&#8217;ll walk you through the features of the new system and how to build this into your theme if you&#8217;re a developer.</p>
<h2>What the menu system offers</h2>
<p>In WordPress 3.0, you&#8217;ll gain another admin screen under your <em>Appearance</em> menu called <em>Menus</em>.  In the screenshot below, I&#8217;ve highlighted four key elements of the page.</p>
<ul>
<li><strong>Theme Locations:</strong>  If your theme supports nav menus, it&#8217;ll register new locations for you to add your custom-created menus.</li>
<li><strong>Individual Menus:</strong>  This is where the names of your menus will appear after you&#8217;ve created them. (Note that the &#8220;+&#8221; sign will create a new menu.)</li>
<li><strong>Add Menu Items:</strong>  There&#8217;ll be several meta boxes containing pages, other post types, categories, other taxonomies, and custom links to your menus.</li>
<li><strong>Menu Items:</strong>  Once you&#8217;ve added menu items to your menu, they will appear under the menu for your configuration.</li>
</ul>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/05/wordpress-nav-menus.png" alt="WordPress Nav Menus" title="A view of the navigation menus screen in WordPress" class="aligncenter" /></p>
<p>Each menu item can has its own configuration section too.  Once the item has been added to the menu, you can open it and edit its attributes, which are standard things you might want to change about any menu.</p>
<ul>
<li><acronym title="Uniform Resource Locator">URL</acronym></li>
<li>Navigation Label</li>
<li>Title Attribute</li>
<li>CSS Classes</li>
<li>Link Relationship (XFN)</li>
<li>Description</li>
<li>Link Target (Please note that a kitten dies every time a link is opened in a new window/tab.)</li>
</ul>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/05/nav-menu-item.png" alt="Nav Menu Item" title="Screenshot of the configuration box for nav menu items in WordPress" class="aligncenter" /></p>
<h2>Registering a menu for a theme (theme location)</h2>
<p>To associate specific menus with locations within our themes, we need to register these locations.  Otherwise, we won&#8217;t know which menu goes where.  There are two functions we can use for this:</p>
<ul>
<li><code>register_nav_menu()</code>:  Registers a single theme location.</li>
<li><code>register_nav_menus()</code>:  An array of locations we want to register.</li>
</ul>
<p>In this example, we&#8217;ll register a single menu called <em>Primary Menu</em> from our theme&#8217;s <code>functions.php</code> file.</p>
<pre><code>add_action( 'init', 'register_my_menu' );

function register_my_menu() {
	register_nav_menu( 'primary-menu', __( 'Primary Menu' ) );
}</code></pre>
<p><code>primary-menu</code> is the slug we&#8217;ll use to identify the menu in code.  <code>Primary Menu</code> is the label we&#8217;ll use to identify the menu in the admin.</p>
<p>Building off that example, we&#8217;ll create multiple menus, which is not much different than registering a single menu.</p>
<pre><code>add_action( 'init', 'register_my_menus' );

function register_my_menus() {
	register_nav_menus(
		array(
			'primary-menu' => __( 'Primary Menu' ),
			'secondary-menu' => __( 'Secondary Menu' ),
			'tertiary-menu' => __( 'Tertiary Menu' )
		)
	);
}</code></pre>
<h2>Displaying a nav menu</h2>
<p>There are two ways to display a nav menu.  One is by calling <a href="http://codex.wordpress.org/Function_Reference/wp_nav_menu" title="WordPress Codex: wp_nav_menu()">wp_nav_menu()</a> within a theme template file.  The other is by using the <em>Navigation Menu</em> widget.</p>
<h3>Displaying a menu within a theme template</h3>
<p>Most themes will call a menu from their <code>header.php</code> template, but menus can be placed anywhere.  The simplest form of calling a nav menu in a theme will look like this:</p>
<pre><code>&lt;?php wp_nav_menu(); ?></code></pre>
<p>That will load the first menu the user created or fall back on a standard page list if no menus exist.  </p>
<p>We want to have a bit more control than that though.  Let&#8217;s call our menu from the previous section (Primary Menu).</p>
<pre><code>&lt;?php wp_nav_menu( array( 'theme_location' => 'primary-menu' ) ); ?></code></pre>
<p>You&#8217;re allowed even more control.  <code>wp_nav_menu()</code> has several parameters you can use when displaying a menu.</p>
<ul>
<li><code>theme_location</code>: The menu to call that is associated with the specific theme location.</li>
<li><code>menu</code>: Call a specific menu ID, slug, or name.</li>
<li><code>container</code>: The element that wraps around the list.  The default is <code>div</code> but can be changed to <code>nav</code> if you&#8217;ve moved on to <acronym title="Hypertext Markup Language">HTML 5</acronym>.</li>
<li><code>container_class</code>: The <acronym title="Cascading Stylesheets">CSS</acronym> class of the container.</li>
<li><code>menu_class</code>:  The <acronym title="Cascading Stylesheets">CSS</acronym> class given to the unordered list.  This defaults to <code>menu</code>.</li>
<li><code>fallback_cb</code>:  A function to call in the event that no menu items have been given.  By default, <code>wp_list_pages()</code> will be called.</li>
<li><code>before</code>: Text that is displayed before the link text but within the link.</li>
<li><code>after</code>: Text that is displayed after the link text but within the link.</li>
<li><code>link_before</code>: Text that is displayed before the link.</li>
<li><code>link_after</code>: Text that is displayed after the link.</li>
<li><code>depth</code>: How many levels the menu should display, which is useful for things like drop-down menus. This is set to <code>0</code> (any level) by default.</li>
<li><code>walker</code>: Allows a custom walker <acronym title="Hypertext Preprocessor">PHP</acronym> class to be defined to create the menu.</li>
<li><code>echo</code>: Whether to display the menu or return it for use in <acronym title="Hypertext Preprocessor">PHP</acronym>.  This defaults to <code>true</code> and displays the menu.</li>
</ul>
<h3>Displaying a menu using the Navigation Menu widget</h3>
<p>By default, WordPress will give you a simple menu widget that will allow you to select any of your custom menus to display.  All you need is a widget-ready theme.</p>
<p>Since using widgets is fairly self-explanatory and the new widget is simple, I&#8217;m going to use this opportunity for a little shameless self promotion.</p>
<p>For those of you that use my <a href="http://themehybrid.com/themes/hybrid" title="Hybrid WordPress theme">Hybrid theme</a>, you know you have the coolest widgets ever because they give you complete control.  Version 0.8 will have a much more advanced Navigation Menu widget that overwrites the WordPress default.  Here&#8217;s a look at what controls you&#8217;ll have.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/05/navigation-menu-widget.png" alt="Navigation Menu Widget" title="Navigation Menu widget in the Hybrid WordPress theme" class="aligncenter" /></p>
<h2>Styling nav menus</h2>
<p>I won&#8217;t be covering how to style menus here.  That&#8217;s a tutorial in and of itself, and there are tons of different ways to style menus.  I do have a couple of tips though.</p>
<p>Use the <code>current-menu-item</code> class to style a menu item whose page is currently being viewed.  This will allow you to highlight the item so the reader will know which page they&#8217;re on.  Here&#8217;s an example from one of my <code>style.css</code> files:</p>
<pre><code>#primary-menu li.current-menu-item a {
	background: #fff url(images/primary-menu-active.png) repeat-x 0 0;
	border-top: none;
	border-bottom: 2px solid #fff;
	}</code></pre>
<p>A solid base to start with is the <a href="http://users.tpg.com.au/j_birch/plugins/superfish/" title="Superfish plugin">Superfish jQuery plugin</a>.  It allows some subtle, but cool, JavaScript functionality and fixes drop-downs in Internet Explorer 6 without having to resort to hacks.</p>
<p>Here&#8217;s a screenshot of a menu I&#8217;ve been working on for a new theme.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/05/menu-screenshot.png" alt="Navigation menu frontend" title="Screenshot of a menu from the Outline theme" class="aligncenter" /></p>
<p>At this point, you should know everything you need to know about handling menus in WordPress.  But, if you continue reading, I have a few more tips that you can use.</p>
<h2>Collapsible menus</h2>
<p>Let&#8217;s suppose you only want a menu to appear when a user has added menu items.  This can allow for a variety of layouts.  In the screenshot below, I&#8217;m using two menus.  But, this allows for up to four different layouts.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/05/collapse-menus.png" alt="Collapsible menus" title="Collapsed navigation menus in WordPress" class="aligncenter" /></p>
<p>The trick here is to make sure there&#8217;s no fallback called.  Let&#8217;s return to our original menu (Primary Menu) and the code for it.</p>
<pre><code>&lt;?php wp_nav_menu( array( 'theme_location' => 'primary-menu', 'fallback_cb' => '' ) ); ?></code></pre>
<p>What I&#8217;ve done is simply tell WordPress that I don&#8217;t want my menu to fall back to another menu if the user hasn&#8217;t given the menu any items.</p>
<h2>Checking if a theme location has a menu</h2>
<p class="alert">Update: Props to <a href="http://www.andrewnacin.com/" title="Andrew Nacin">Andrew Nacin</a> for adding the <code>has_nav_menu()</code> function after reading this section of the article.</p>
<p><del>WordPress currently has no conditional tag to check if a menu has been set to a specific theme location.</del> WordPress has a conditional tag called <code>has_nav_menu()</code> to check if a menu has been set to a specific theme location.  Let&#8217;s suppose we&#8217;re creating a container with a menu and a search form.  But, if no menu is set for the theme location, we don&#8217;t want either to appear.</p>
<p>In the screenshot, you can see that neither appear in one scenario and both appear in the other.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/05/menu-with-search.png" alt="Collapsible menu container" title="Collapsed menu and search form in WordPress" class="aligncenter" /></p>
<p>When you call your menu by theme location, you can first check to see if a menu is associated with the location.  Note that we&#8217;re checking the theme location slug and not a menu name or ID.</p>
<pre><code>&lt;?php if ( has_nav_menu( 'primary-menu' ) ) { ?>

	&lt;div class="nav-container">
		&lt;?php wp_nav_menu( array( 'theme_location' => 'primary-menu' ) ); ?>
		&lt;?php get_search_form(); ?>
	&lt;/div>

} ?></code></pre>
<h2>Allowing more menu containers</h2>
<p>The menu system will only allow for <code>&lt;div></code> and <code>&lt;nav></code> as a menu container by default.  This is likely all you&#8217;ll ever need.  If for some reason your menu needs to be wrapped by something else, you can allow for new containers.</p>
<pre><code>add_filter( 'wp_nav_menu_container_allowedtags', 'my_menu_allowed_tags' );

function my_menu_allowed_tags( $tags ) {
	$tags[] = 'p';
	return $tags;
}</code></pre>
<p>Note the the <code>&lt;p></code> tag isn&#8217;t something I&#8217;d recommend using to wrap a list.  It&#8217;s just an example.</p>
<h2>Getting a list of all theme locations</h2>
<p>If you need to list your theme&#8217;s menu locations, use the code below.  It will return an array of the locations.</p>
<pre><code>$locations = get_nav_menu_locations();</code></pre>
<h2>Creating a menu</h2>
<p>Most theme authors shouldn&#8217;t have a need to use this function, but there may be cases when it&#8217;s needed.  In most situations, you should use the theme location feature (<code>register_nav_menu()</code>) rather than this.  But, if you need to programmatically create a menu, do so using the <code>wp_create_nav_menu()</code> function.</p>
<pre><code>wp_create_nav_menu( 'Menu Name', array( 'slug' => 'menu-slug' ) );</code></pre>
<h2>Checking if a specific menu exists</h2>
<p>This is another function not likely needed by theme developers but may come in handy.  It allows you to check if a menu exists by ID, name, or slug.</p>
<pre><code>if ( is_nav_menu( 'menu-slug' ) )
	/* Do something if the menu exists. */
else
	/* Do something if the menu doesn't exist. */</code></pre>
<h2>Have fun with your menus</h2>
<p>While there are certainly other features I love about WordPress 3.0 more, the new menu system is the feature that&#8217;ll help me the most as a theme developer.  There&#8217;s also a ton of stuff you can do with menus that I couldn&#8217;t possibly cover in this tutorial.  I&#8217;m going to leave that up to your imagination.</p>
<p>I do have one request from any plugin developer that&#8217;s up for a challenge:  a &#8220;menu logic&#8221; plugin akin to Alan Trewartha&#8217;s awesome <a href="http://wordpress.org/extend/plugins/widget-logic" title="Widget Logic WordPress plugin">Widget Logic</a> plugin.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/06/01/goodbye-headaches-hello-menus/feed</wfw:commentRss>
		<slash:comments>207</slash:comments>
		</item>
		<item>
		<title>Custom post types in WordPress</title>
		<link>http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress</link>
		<comments>http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress#comments</comments>
		<pubDate>Thu, 29 Apr 2010 15:20:39 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2336</guid>
		<description><![CDATA[The ultimate guide for understanding, creating, and using custom post types with WordPress.]]></description>
			<content:encoded><![CDATA[<p>One of the things I&#8217;ve been hoping would be implemented in WordPress for years is the ability to create custom content types.  The inability to do this has been WordPress&#8217; weakest point when compared to rivals in the <acronym title="Content Management System">CMS</acronym> market.</p>
<p>In WordPress 3.0, we&#8217;ll have the capability to easily create and manage content via <em>custom post types</em>.  Not only that, but you won&#8217;t have to rely on a plugin to do this for you.  It can be done via your theme&#8217;s <code>functions.php</code> file with a few lines of code.</p>
<p>There are other 3.0 features such as menu management and multi-site, but this is the most promising feature coming.  In this tutorial, I&#8217;ll walk you through the creation of custom post types and how they can be used for your blog.</p>
<p class="alert">Note that I&#8217;ll use &#8220;post&#8221; and &#8220;posts&#8221; a lot to refer to custom post types in this tutorial.  I&#8217;ll try to separate this from what you likely know as a post by calling it a &#8220;blog post.&#8221;</p>
<h2>What are custom post types?</h2>
<p>Don&#8217;t be confused by the term &#8220;post&#8221; in the name.  It is actually an extremely generic term and should not be considered the same thing as a blog post.  If you prefer, you can replace it with &#8220;content&#8221; instead. </p>
<p>Custom post types don&#8217;t have any strict rules that define what they are.  They can represent any type of content you want.  For example, WordPress ships with several default post types.</p>
<ul>
<li>Blog Posts</li>
<li>Pages</li>
<li>Attachments</li>
<li>Revisions</li>
<li>Nav Menus (WordPress 3.0)</li>
</ul>
<p>You should think of them as a way to create, edit, and store information in the same way as blog posts but with much more creative control.</p>
<p>One thing I would warn against is trying to separate your blog posts in this way.  You have categories, tags, and custom taxonomies at your disposal if you&#8217;re just looking for a way to label them.</p>
<h2>Ideas for custom post types</h2>
<p>While WordPress ships with some good default post types that are great for most sites, some of us need alternatives.  I&#8217;ll list some things below that I think would be useful and link to examples if I can.</p>
<ul>
<li>Real estate listings.</li>
<li>Event calendar (I know a lot of folks are interested in this).</li>
<li><a href="http://popcritics.com/movies" title="Pop Critics Movie Database">Movie Database</a></li>
<li><a href="http://popcritics.com/books" title="Pop Critics Book Database">Book Database</a></li>
<li>A <a href="http://justintadlock.com/blog/wp-content/uploads/2010/04/forum-post-type.png" title="Forum built with custom post types and taxonomies">forum</a> without a lot of integration problems.</li>
<li>A <a href="http://justintadlock.com/blog/wp-content/uploads/2010/04/issue-tracker.png" title="Screenshot of a bug and issue tracker built with WordPress">ticket system</a> like the <a href="http://core.trac.wordpress.org" title="Trac: WordPress core">WordPress Trac</a>.</li>
<li>Design <a href="http://themehybrid.com/showcase" title="Theme Hybrid Showcase">gallery/showcase</a>.</li>
</ul>
<p>Don&#8217;t let your imagination be limited by my list of examples.  Also, look for some information on the forum and ticket system ideas from me in the future.  Those two are projects I&#8217;ve been building and would love to get some feedback on.</p>
<h2>Custom post types in the admin</h2>
<p>Once you create a custom post type, WordPress can handle all of the admin stuff for you.  By default, the administration interface will be the same as what you get with blog posts and pages.  Of course, you&#8217;re welcome to get more advanced with it and change it into whatever you like.</p>
<p>In this tutorial, I&#8217;m creating a post type called <em>Super Duper</em>.  With the minimum post type settings, the admin will look like the screenshot below (click image for more detailed view):</p>
<p><a href="http://justintadlock.com/blog/wp-content/uploads/2010/04/custom-post-types-large.png" title="Create and edit screens for WordPress custom post types"><img src="http://justintadlock.com/blog/wp-content/uploads/2010/04/add-new-post-type.png" alt="Add new post with a custom post type" title="Custom post types in the WordPress admin" /></a></p>
<h2>Creating custom post types (basics)</h2>
<p>WordPress 2.9 introduced the <a href="http://codex.wordpress.org/Function_Reference/register_post_type" title="WordPress Codex: register_post_type()">register_post_type()</a> function.  It didn&#8217;t do a lot at the time, but WordPress 3.0 will make this a powerful tool.</p>
<p>To get the basic functionality of a custom post type working, we hardly have any code to input.  Before you start, you at least need a few things: a name, two labels, and whether your post type will be public (you&#8217;ll likely want this).</p>
<p>You can either create a plugin file or use your theme&#8217;s <code>functions.php</code> file to add the code.  I will assume at this point of the tutorial that you know how to work with at least one of those two things.</p>
<p>Let&#8217;s set up our <em>Super Duper</em> post type.</p>
<pre><code>add_action( 'init', 'create_my_post_types' );

function create_my_post_types() {
	register_post_type( 'super_duper',
		array(
			'labels' => array(
				'name' => __( 'Super Dupers' ),
				'singular_name' => __( 'Super Duper' )
			),
			'public' => true,
		)
	);
}</code></pre>
<p>You&#8217;ll notice that there&#8217;s not a lot going on there.  We added two parameters: a post type name and an array of arguments.  All of the possible arguments are detailed in the next section.</p>
<p>If all you&#8217;ll ever want to do is something as basic as having a title field and content textarea, you can skip over the next portion of this tutorial.</p>
<h2>Creating custom post types (in detail)</h2>
<p>In the basic section above, we used two arguments to create our custom post type.  However, the <code>register_post_type()</code> function has well over 20 arguments you can use.  It gives you a lot of control over the specifics of your post type without a lot of hassle.  You can mix and match these in all sorts of ways that I can&#8217;t even come close to covering in this tutorial.</p>
<p>Below, I&#8217;ll describe each of the arguments available for use.  Each section will have an example of how to add the argument to the arguments array.</p>
<h4>labels</h4>
<p>The <code>labels</code> argument is an array of strings that represents your post type in the admin.  Each string is a bit of text shown for particular function in the admin.  By default, non-hierarchical post types will have text with &#8220;post&#8221; in them and hierarchical post types will have text with &#8220;page&#8221; in them.  </p>
<p>It is particularly important that you make these strings translatable if you&#8217;re creating a plugin for public use.</p>
<p>This list is a set of general examples of when each string is used.  However, each may be used in multiple places in the admin.</p>
<ul>
<li><code>name</code>: The plural form of the name of your post type.</li>
<li><code>singular_name</code>: The singular form of the name of your post type.</li>
<li><code>add_new</code>: The menu item for adding a new post.</li>
<li><code>add_new_item</code>: The header shown when creating a new post.</li>
<li><code>edit</code>: The menu item for editing posts.</li>
<li><code>edit_item</code>: The header shown when editing a post.</li>
<li><code>new_item</code>: Shown in the favorites menu in the admin header.</li>
<li><code>view</code>: Used as text in a link to view the post.</li>
<li><code>view_item</code>: Shown alongside the permalink on the edit post screen.</li>
<li><code>search_items</code>: Button text for the search box on the edit posts screen.</li>
<li><code>not_found</code>: Text to display when no posts are found through search in the admin.</li>
<li><code>not_found_in_trash</code>: Text to display when no posts are in the trash.</li>
<li><code>parent</code>: Used as a label for a parent post on the edit posts screen. Only useful for hierarchical post types.</li>
</ul>
<pre><code>'labels' => array(
	'name' => __( 'Super Dupers' ),
	'singular_name' => __( 'Super Duper' ),
	'add_new' => __( 'Add New' ),
	'add_new_item' => __( 'Add New Super Duper' ),
	'edit' => __( 'Edit' ),
	'edit_item' => __( 'Edit Super Duper' ),
	'new_item' => __( 'New Super Duper' ),
	'view' => __( 'View Super Duper' ),
	'view_item' => __( 'View Super Duper' ),
	'search_items' => __( 'Search Super Dupers' ),
	'not_found' => __( 'No super dupers found' ),
	'not_found_in_trash' => __( 'No super dupers found in Trash' ),
	'parent' => __( 'Parent Super Duper' ),
),</code></pre>
<h4>description</h4>
<p>The <code>description</code> argument allows you to write a text string of your post type.  Thus far, I haven&#8217;t seen this used anywhere in the WordPress admin, but I&#8217;m sure custom post type plugins could take advantage of this.</p>
<pre><code>'description' => __( 'A super duper is a type of content that is the most wonderful content in the world. There are no alternatives that match how insanely creative and beautiful it is.' ),</code></pre>
<h4>public</h4>
<p>The <code>public</code> argument is a kind of catchall argument for several other arguments and defaults to <code>false</code>.  Depending on whether it&#8217;s set to <code>true</code> or <code>false</code>, it&#8217;ll automatically decide what other arguments should be unless they&#8217;re specifically defined.  If you&#8217;re looking for finer control over the public arguments, there are three specific arguments you may set:</p>
<ul>
<li><code>show_ui</code>: Whether to show the administration screens.</li>
<li><code>publicly_queryable</code>: Whether queries for this post type can be performed from the front end.</li>
<li><code>exclude_from_search</code>: Whether the posts should appear in search results.</li>
</ul>
<pre><code>'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,</code></pre>
<h4>menu_position</h4>
<p>By default, a new post type is added after the <em>Comments</em> menu item in the admin.  But, you have to ability to move it to a position more suitable for you.  Default WordPress menu items are set apart by integrals of 5.  For example, using <code>20</code> will add your menu item after <em>Pages</em>.</p>
<pre><code>'menu_position' => 20,</code></pre>
<h4>menu_icon</h4>
<p>New post types will default to the <em>Posts</em> menu icon, but if you want to mix it up a bit or give your post type some separation from other elements, you can define a custom icon.  You only have to input a a custom <acronym title="Uniform Resource Locator">URL</acronym> to an image file.</p>
<pre><code>'menu_icon' => get_stylesheet_directory_uri() . '/images/super-duper.png',</code></pre>
<h4>hierarchical</h4>
<p>The <code>hierarchical</code> argument allows you to choose whether you want your post type to be hierarchical.  It defaults to <code>false</code>.  If you set it to <code>true</code>, your posts will behave like pages in WordPress.</p>
<pre><code>'hierarchical' => true,</code></pre>
<h4>query_var</h4>
<p>The <code>query_var</code> argument allows you to control the query variable used to get posts of this type.  For example, you could use it with the <code>query_posts()</code> function or <code>WP_Query</code> class.  This will default to the name of your taxonomy.</p>
<pre><code>'query_var' => true,</code></pre>
<h4>capability_type / capabilities</h4>
<p>The <code>capability_type</code> argument is another catchall argument for several more specific arguments and defaults to <code>post</code>.  It allows you to define a custom set of capabilities, which are permissions to edit, create, and read your custom post type.  If you&#8217;re unfamiliar with capabilities, I highly recommend reading my guide on <a href="http://justintadlock.com/archives/2009/08/30/users-roles-and-capabilities-in-wordpress" title="Users, roles, and capabilities in WordPress">users, roles, and capabilities</a>.</p>
<p>If you just want to keep the same permissions you have with blog posts, leave this at the default.  Otherwise, you can either set <code>capability_type</code> to something custom or define each specific capability in the <code>capabilities</code> array.</p>
<ul>
<li><code>edit_post</code>: Whether someone can create and edit a specific post of this post type.</li>
<li><code>edit_posts</code>: Capability that allows editing posts of this post type.</li>
<li><code>edit_others_posts</code>: Capability that allows editing of others posts.</li>
<li><code>publish_posts</code>: Capability to grant publishing of these types of posts.</li>
<li><code>read_post</code>: Capability that controls reading of a specific post of this post type.</li>
<li><code>read_private_posts</code>: Capability to allow reading of private posts.</li>
<li><code>delete_post</code>: Capability that grants the privelege of deleting posts.</li>
</ul>
<p>For most people that need control over these things, it&#8217;s easier to just change <code>capability_type</code> to something like <code>super_duper</code>.  WordPress will automatically switch the other caps to follow this pattern.  For example, the <code>edit_post</code> capability would become <code>edit_super_duper</code>.</p>
<p>Of course, capability control means nothing without being able to choose who has the capabilities.  That&#8217;s what my <a href="http://justintadlock.com/archives/2009/09/17/members-wordpress-plugin" title="Members: WordPress Plugin">Members plugin</a> was created for.  It&#8217;s ideal for this scenario.</p>
<pre><code>/* Global control over capabilities. */
'capability_type' => 'super_duper',

/* Specific control over capabilities. */
'capabilities' => array(
	'edit_post' => 'edit_super_duper',
	'edit_posts' => 'edit_super_dupers',
	'edit_others_posts' => 'edit_others_super_dupers',
	'publish_posts' => 'publish_super_dupers',
	'read_post' => 'read_super_duper',
	'read_private_posts' => 'read_private_super_dupers',
	'delete_post' => 'delete_super_duper',
),</code></pre>
<h4>supports</h4>
<p>The <code>supports</code> argument allows you to define what meta boxes and other fields will appear on the screen when editing or creating a new post.  This defaults to <code>title</code> and <code>editor</code>.  There are several available options:</p>
<ul>
<li><code>title</code>: Text input field to create a post title.</li>
<li><code>editor</code>: Content input box for writing.</li>
<li><code>comments</code>: Ability to turn comments on/off.</li>
<li><code>trackbacks</code>: Ability to turn trackbacks and pingbacks on/off.</li>
<li><code>revisions</code>: Allows revisions to be made of your post.</li>
<li><code>author</code>: Displays a select box for changing the post author.</li>
<li><code>excerpt</code>: A textarea for writing a custom excerpt.</li>
<li><code>thumbnail</code>: The thumbnail (featured image in 3.0) uploading box.</li>
<li><code>custom-fields</code>: Custom fields input area.</li>
<li><code>page-attributes</code>: The attributes box shown for pages. This is important for hierarchical post types, so you can select the parent post.</li>
</ul>
<pre><code>'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail' ),</code></pre>
<h4>rewrite</h4>
<p>The <code>rewrite</code> argument allows you to define the permalink structure of your posts when viewing the single post.  For example, you may want to have a structure like <code>yoursite.com/cool/post-name</code>.  WordPress will set up a default structure based on your taxonomy name.  The <code>rewrite</code> argument can be set to <code>true</code>, <code>false</code>, or an array of values.  It takes two arguments:</p>
<ul>
<li><code>slug</code>: The slug you&#8217;d like to prefix your posts with.</li>
<li><code>with_front</code>: Whether your post type should use the front base from your permalink settings (for example, if you prefixed your structure with <code>/blog</code> or <code>/archives</code>).</li>
</ul>
<pre><code>'rewrite' => array( 'slug' => 'cool', 'with_front' => false ),</code></pre>
<h4>taxonomies</h4>
<p>If you have some preexisting taxonomies, you can allow posts of this type to also use those taxonomies.  You just have to set an array of taxonomy names that you&#8217;d like for it to use.  WordPress will handle all the administration features for you.</p>
<p>Note that I&#8217;ll be covering the integration of post types and taxonomies in more depth in a future tutorial.</p>
<pre><code>'taxonomies' => array( 'post_tag', 'category '),</code></pre>
<h4>can_export</h4>
<p>You can use the <code>can_export</code> argument to decide whether posts of your post type can be exportable via the WordPress export tool.  By default, this is set to <code>true</code>.</p>
<pre><code>'can_export' => true,</code></pre>
<h4>register_meta_box_cb</h4>
<p>This feature will likely only be useful to developers.  You can create a custom callback function that is called when the meta boxes for the post form are set up.</p>
<pre><code>'register_meta_box_cb' => 'your_callback_function_name',</code></pre>
<h4>permalink_epmask</h4>
<p>I won&#8217;t pretend to know much about permalink endpoint masks.  I just know you can define a custom one for your post type.  Most of you won&#8217;t need this.  For the purposes of this tutorial, I&#8217;ll leave this at the default.</p>
<pre><code>'permalink_epmask' => EP_PERMALINK,</code></pre>
<h2>Viewing a custom post type</h2>
<p>WordPress will show the singular view of your custom post types without any extra work.  Once you create a new post, you&#8217;ll be able to view it by clicking on the <em>View Post</em> link.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/04/view-post-link.png" alt="View post link in the WordPress admin" title="View custom post type link" width="600" height="186" class="aligncenter size-full wp-image-2343" /></p>
<p>If your WordPress theme has a <code>single.php</code> template, this will be used to display your custom post type.  If not, it will fall back to the <code>index.php</code> template.  Since this is a &#8220;custom&#8221; post type, I&#8217;ll assume you want to customize how it&#8217;s output.  To overwrite the default, you can create a custom template.  Our template will be called <code>single-super_duper.php</code>.</p>
<p>You can go as crazy as you like with this template.  All of the standard WordPress template tags will work just fine here as well.  I could give you endless pages of examples of how to customize this, but I won&#8217;t.  I&#8217;d rather allow you to get creative on your own.</p>
<p class="alert">If you&#8217;re using a smart theme like <a href="http://themehybrid.com/themes/hybrid" title="Hybrid WordPress theme framework">Hybrid</a>, this template will be <code>super_duper.php</code>.  <em>Hybrid</em> has long supported custom post types and uses a different template hierarchy, which is detailed in its tutorials.  WordPress 3.0 will be a fun time to use this theme because of the ultimate control it gives you over templates like this.</p>
<h2>Showing multiple posts from our custom post type</h2>
<p>Let&#8217;s suppose I wanted to show the 10 latest &#8220;super dupers&#8221; I&#8217;ve published.  We&#8217;ll use the standard WordPress loop for this and customize it however we like.  Here&#8217;s a basic example:</p>
<pre><code>&lt;?php $loop = new WP_Query( array( 'post_type' => 'super_duper', 'posts_per_page' => 10 ) ); ?>

&lt;?php while ( $loop->have_posts() ) : $loop->the_post(); ?>

	&lt;?php the_title( '&lt;h2 class="entry-title">&lt;a href="' . get_permalink() . '" title="' . the_title_attribute( 'echo=0' ) . '" rel="bookmark">', '&lt;/a>&lt;/h2>' ); ?>

	&lt;div class="entry-content">
		&lt;?php the_content(); ?>
	&lt;/div>
&lt;?php endwhile; ?></code></pre>
<p>Obviously, this is an extremely simple example.  Understanding what you can do with the loop is outside the scope of this tutorial.  The most important part is giving the <code>post_type</code> argument the name of our post type.</p>
<h2>Getting the post type of a post</h2>
<p>An old, yet useful, function in WordPress is <a href="http://codex.wordpress.org/Function_Reference/get_post_type" title="WordPress Codex: get_post_type()">get_post_type()</a>.  It allows you to check the current (if no post object or ID input) or a specific post&#8217;s post type.  It will return the name of the post type for the post as a string.</p>
<pre><code>$post_type = get_post_type( $post_id );</code></pre>
<h2>Checking if a post type exists</h2>
<p>WordPress 3.0 will introduce a conditional tag called <code>is_post_type()</code> whose purpose is twofold.  Its first purpose is to check whether a post type or types exist.  In order to use it, you can input a custom post type name or array of names into the function call.</p>
<pre><code>if ( is_post_type( 'super-duper' ) )
	echo 'Super Dupers are working!';
else
	echo 'Super Dupers are not working!';</code></pre>
<h2>Checking if a post is of specified post type</h2>
<p>The second purpose of the <code>is_post_type()</code> function allows you to check a specific post against a specific post type(s).  Let&#8217;s assume we want to check if one of our posts has the <code>super_duper</code> post type.</p>
<pre><code>if ( is_post_type( 'super_duper', $post_id ) )
	echo 'This is a not a blog post.  It is a super duper!';
else
	echo 'This is not a super duper. [insert sad face]';</code></pre>
<h2>Checking if a post type is hierarchical</h2>
<p>You may want to treat hierarchical post types differently than other post types.  To figure out if a post type is hierarchical, you can use the <code>is_post_type_hierarchical()</code> conditional tag.  It will take in a post type name, post ID, or post object as its single parameter.</p>
<p>For example, let&#8217;s check if our super duper post type is hierarchical:</p>
<pre><code>if ( is_post_type_hierarchical( 'super_duper' ) )
	'Super Dupers should not be hierarchical!';
else
	'Super Dupers are definitely not hierarchical! We stick it to the man!';</code></pre>
<h2>Getting a post type object</h2>
<p>In some scenarios, you may want to get the arguments (all those things we went over earlier) for a specific post type.  It is extremely important for plugin/theme authors to respect these arguments when creating plugins/themes that interact with custom post types.</p>
<p>Let&#8217;s suppose we want to call a specific function if the super duper post type has set <code>show_ui</code> to <code>true</code>.</p>
<pre><code>$post_type = get_post_type_object( 'super_duper' );

if ( $post_type->show_ui )
	custom_function_name();</code></pre>
<h2>Adding and removing support for post type features</h2>
<p>The <code>add_post_type_supprt()</code> function is no different than using the <code>supports</code> argument when first creating your post type.  This is likely more useful if you&#8217;re using a plugin/theme that has defined a custom post type.</p>
<p>So, let&#8217;s suppose you&#8217;re using a plugin that creates a new post type for you.  Your post type doesn&#8217;t have support for thumbnails, but you think this feature would work well on your site.</p>
<pre><code>add_post_type_support( 'post_type', 'thumbnail' );</code></pre>
<p>The opposite of this function is <code>remove_post_type_support()</code>.  So, let&#8217;s further suppose that your plugin author added support for excerpts, but you don&#8217;t want to use this feature.</p>
<pre><code>remove_post_type_support( 'post_type', 'excerpt' );</code></pre>
<h2>Checking if a post type supports a specific feature</h2>
<p>As a plugin/theme author, this will likely be useful.  You wouldn&#8217;t want to try and display stuff that doesn&#8217;t exist for a custom post type.  For example, your theme may wrap post content with a <code>&lt;div></code> or something of that sort.  This is fairly common.  But, you may want to remove it if the post type doesn&#8217;t have written content.</p>
<pre><code>&lt;?php if ( post_type_supports( 'super_duper', 'editor' ) ) { ?>

	&lt;div id="post-&lt;?php the_ID(); ?>" &lt;?post_class(); ?>>
		&lt;?php the_content(); ?>
	&lt;/div>

&lt;?php } ?></code></pre>
<p>Be careful with this though.  A post type may have other means of defining something like the content, and this should only be taken as an example of how to use the <code>post_type_supports()</code> function.</p>
<h2>Getting registered post types for use in PHP</h2>
<p>As a plugin/theme developer, you may need to get all the registered post types for use in a function of your plugin/theme.  You&#8217;d use the <a href="http://codex.wordpress.org/Function_Reference/get_post_types" title="WordPress Codex: get_post_types()">get_post_types()</a> function for this.</p>
<p>In the below example, I&#8217;ll output a list of post types by singular label that are shown in search results.</p>
<pre><code>&lt;?php $types = get_post_types( array( 'exclude_from_search' => false ), 'objects' ); ?>

&lt;ul>
	&lt;?php foreach ( $types as $type )
		echo '&lt;li>' . $type->singular_label . '&lt;/li>';
	?>
&lt;/ul></code></pre>
<h2>Help! I&#8217;m getting a 404!</h2>
<p>If you&#8217;re getting a 404 message when trying to view a post, don&#8217;t worry.  This is supposed to happen when setting up new post types.  The easiest way to fix this is to simply visit your <em>Settings > Permalinks</em> page.  You don&#8217;t have to save your permalinks but just visit the page.  This will flush your rewrite rules.</p>
<p>If you&#8217;re a plugin author, you can save yourself some support questions by flushing the rewrite rules on activation of your plugin.</p>
<h2>Is this a theme or plugin feature?</h2>
<p>I&#8217;ve had a hard time trying to decide which to call it, and have ultimately decided that it&#8217;s both.  It&#8217;s a marriage of the two because both need to be in sync to fully enjoy the benefits of custom post types.</p>
<p>More than likely, you&#8217;ll see post types registerd from within a plugin.  But, they have to be displayed by your theme.  If you&#8217;re creating this all yourself, you can simply drop it all in your theme.</p>
<p>If you&#8217;re a theme author, you should be aware that plugins may add new post types.  Do yourself and your users a favor by not assuming too much.  Keep your code flexible enough to give a default view for custom post types and easy enough to handle when creating custom templates for those post types.</p>
<h2>The tip of the iceberg</h2>
<p>I haven&#8217;t even scratched the surface of what&#8217;s possible with custom post types.  Even the new navigation menus feature of WordPress 3.0 will be built with them.  While I know some people in the community don&#8217;t agree with this decision, I wanted to point it out because it&#8217;s a unique example of what&#8217;s possible.</p>
<p>Of my list of about 1,000 things I wanted to share in this tutorial, I might have covered about 20 of them.  Given enough free time, I could write a book on using custom post types.  Some stuff should be left open to exploration though, and I encourage you to try everything I&#8217;ve written about and move beyond this tutorial to creating something unique for your site.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress/feed</wfw:commentRss>
		<slash:comments>248</slash:comments>
		</item>
		<item>
		<title>Looking forward to WordPress 3.0</title>
		<link>http://justintadlock.com/archives/2010/03/24/looking-forward-to-wordpress-3-0</link>
		<comments>http://justintadlock.com/archives/2010/03/24/looking-forward-to-wordpress-3-0#comments</comments>
		<pubDate>Wed, 24 Mar 2010 08:35:50 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2310</guid>
		<description><![CDATA[WordPress 3.0 will be a major milestone in the platform's life, allowing users to mold their sites into anything they want.]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s typically a ton of hype surrounding new WordPress releases, and WordPress 3.0 certainly won&#8217;t be short of people singing its praises.  This upcoming release might even have more hype than usual because the sheer number of new features will be overwhelming.</p>
<p>When WordPress 3.0 is released, it&#8217;ll mark the release of several things I&#8217;ve been waiting for in the last couple of years.  It&#8217;ll be at a point where it can be molded to create any type of website.</p>
<p>If I were to dub this release anything it&#8217;d be <em>WordPress: Custom</em>.</p>
<h2>What makes this release special</h2>
<p>I consider myself an <em>ideas</em> person.  I can sit for hours just playing around with WordPress and trying to make it do different things for fun.  There are some things I&#8217;ve wished I could do for a long time just with my blog here, but the system hadn&#8217;t quite reached that point.</p>
<p>Not that some of those things were impossible.  They simply weren&#8217;t worth the time and effort.</p>
<p>WordPress 3.0 removes a barrier that&#8217;s been in place for a long time:  the ability to create our sites on our own terms.  No longer will you be bound to terms like &#8220;post&#8221; and &#8220;page&#8221; or &#8220;tag&#8221; and &#8220;category.&#8221;  You&#8217;ll be able to simply create a site and call things what you want.</p>
<p>Custom post types and extra functionality added to custom taxonomies will see to that.  I only hope that this puts an end to that dreadful phrase &mdash; &#8220;WordPress as a <acronym title="Content Management System">CMS</acronym>.&#8221;</p>
<h2>WordPress 3.0 features</h2>
<p>Custom post types and taxonomies aren&#8217;t the only thing to be excited about.  WordPress 3.0 will offer a slew of new features for both developers and end users.</p>
<p>As usual, I&#8217;m lining up some tutorials for the next release.  But, I&#8217;m going to let you pick which tutorials you&#8217;re most interested in this time around (you can probably tell what I&#8217;m most excited about).  Below is a list of features that I&#8217;m interested in and would be willing to write about.</p>
<ul>
<li><strong>Custom post types</strong><br />
		These allow you to create any post/content type you like, set with permalinks, admin pages, and all the works.  You can go as simple as what I&#8217;m planning for my <a href="http://justintadlock.com/blog/wp-content/uploads/2010/01/future-jt-home.png" title="Future home page of JustinTadlock.com">home page</a> or as complex as something like a <a href="http://justintadlock.com/blog/wp-content/uploads/2010/03/issue-tracker.png" title="Issue tracker">bug and issue tracker</a>.</li>
<li><strong>Custom taxonomies</strong><br />
		I&#8217;ve previously written on <a href="http://justintadlock.com/archives/2009/05/06/custom-taxonomies-in-wordpress-28" title="Custom taxonomies in WordPress 2.8">custom taxonomies</a>, but there&#8217;s a ton of new features coming along like hierarchical taxonomies and taxonomies for any post type.</li>
<li><strong>Custom post statuses</strong><br />
		By default, we have a few different statuses we can set our posts to.  In 3.0, we can create new post statuses to use within our projects.  Right now, this probably still needs some more work.</li>
<li><strong>Navigation menus</strong><br />
		The day will finally come when you no longer have to climb mountains to get the navigation you want.  You&#8217;ll have a simple click, drag, and drop interface to create custom menus.</li>
<li><strong>Editor stylesheets</strong><br />
		Themes will be able to package a stylesheet for the post editor that matches the look and feel of their theme content areas.</li>
<li><strong>Shortlinks</strong><br />
		Don&#8217;t like posting long <acronym title="Uniform Resource Locator">URL</acronym>s on site&#8217;s like Twitter? A new shortlink function (that can be enhanced by plugins) will be packaged in.</li>
<li><strong>Custom headers and backgrounds</strong><br />
		Custom headers have been around for a while, but the feature is getting an upgrade.  And, the ability for theme devs to allow users to have a custom background will be included.</li>
<li><strong>Standardized comment form</strong><br />
		One of the things that&#8217;s always bugged me is that it has been hard for plugin authors to add extra functionality to a theme&#8217;s comment form.  This feature will open several doors for cool plugins.</li>
<li><strong>Login form</strong><br />
		You won&#8217;t have to use a hacked up login form of your own anymore.  WordPress will have a function for outputting this and allow your users to log in easily.  And, I can think of a few things that could make this valuable for plugin authors.</li>
<li><strong>User meta functions</strong><br />
		Like our post meta functions, we&#8217;ll be getting a equal set of easy-to-use user meta functions that allow us to update user metadata.</li>
<li><code>get_generic_template()</code> <strong>function</strong><br />
		This will allow you to properly load special templates outside of the WordPress templating system.</li>
<li><code>home_url()</code> <strong>and</strong> <code>site_url()</code><br />
		Two new, much-needed functions for appropriately displaying the <acronym title="Uniform Resource Locator">URL</acronym> of pages.</li>
</ul>
<p>No, I haven&#8217;t listed all the features coming, just the ones I&#8217;m most interested in.  I&#8217;ll leave things like the WordPress and <acronym title="WordPress Multi-user">WPMU</acronym> merge for people more knowledgeable about <acronym title="Multi-user">MU</acronym>.</p>
<p>So, take your pick.  What are you the most interested in learning about?</p>
<p>I also hope this provides some of you a chance to get some of your questions in, so I&#8217;ll know to cover them in the tutorials.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/03/24/looking-forward-to-wordpress-3-0/feed</wfw:commentRss>
		<slash:comments>91</slash:comments>
		</item>
		<item>
		<title>Showing custom post types on your home/blog page</title>
		<link>http://justintadlock.com/archives/2010/02/02/showing-custom-post-types-on-your-home-blog-page</link>
		<comments>http://justintadlock.com/archives/2010/02/02/showing-custom-post-types-on-your-home-blog-page#comments</comments>
		<pubDate>Tue, 02 Feb 2010 08:22:47 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2283</guid>
		<description><![CDATA[How to add custom post types to your blog post rotation on your WordPress home (blog/posts) page.]]></description>
			<content:encoded><![CDATA[<p>In the last few days, I&#8217;ve shown a few people a <a href="http://justintadlock.com/blog/wp-content/uploads/2010/02/justin-tadlock-future.png" title="Justin Tadlock future home page">screenshot</a> of something I&#8217;ve been working on for this site.  The screenshot is of a home page displaying custom post types and not just the <code>post</code> post type.  After numerous requests for the code to do this, I figured it&#8217;d be much easier to share it here.</p>
<p>WordPress version 3.0 will make creating <a href="http://core.trac.wordpress.org/ticket/9674" title="WordPress Trac: Better support for custom post types">custom post types</a> extremely simple.  But, the techniques I&#8217;ll point out in this tutorial can be used with previous versions of WordPress.</p>
<h2>Changing the post type on the home page</h2>
<p>By default, WordPress shows the <code>post</code> post type on your home page.  Let&#8217;s suppose we want to show several post types in addition to posts:</p>
<ul>
<li><code>page</code> (yes, regular pages)</li>
<li><code>album</code></li>
<li><code>movie</code></li>
<li><code>quote</code></li>
</ul>
<p>To add these, open your theme&#8217;s <code>functions.php</code> file and paste this <acronym title="Hypertext Preprocessor">PHP</acronym> code into it:</p>
<pre><code>add_filter( 'pre_get_posts', 'my_get_posts' );

function my_get_posts( $query ) {

	if ( is_home() &#038;&#038; false == $query->query_vars['suppress_filters'] )
		$query->set( 'post_type', array( 'post', 'page', 'album', 'movie', 'quote', 'attachment' ) );

	return $query;
}</code></pre>
<p>That&#8217;s all there is to it.</p>
<p>You may have noticed the addition of the <code>attachment</code> post type even though I didn&#8217;t mention adding it.  This is something I highly recommend adding if you&#8217;ll be showing any attachment images on your home page  For example, if you have a gallery on your home page, the images won&#8217;t appear without adding the <code>attachment</code> post type.</p>
<h2>Showing the post types in your feed</h2>
<p>Realizing that many of you might want to also add these post types to your feed to match your blog, a small change in the code is required.  All you need to do is change this line:</p>
<pre><code>if ( is_home() )</code></pre>
<p>We&#8217;ll use the <code>is_feed()</code> conditional tag:</p>
<pre><code>if ( ( is_home() &#038;&#038; false == $query->query_vars['suppress_filters'] ) || is_feed() )</code></pre>
<p>Now, you can have custom post types in your regular blog post rotation and your feed.  Enjoy and look for more custom post type tutorials soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/02/02/showing-custom-post-types-on-your-home-blog-page/feed</wfw:commentRss>
		<slash:comments>80</slash:comments>
		</item>
		<item>
		<title>Sidebar (widget area) descriptions in WordPress 2.9</title>
		<link>http://justintadlock.com/archives/2009/11/24/sidebar-widget-area-descriptions-in-wordpress-2-9</link>
		<comments>http://justintadlock.com/archives/2009/11/24/sidebar-widget-area-descriptions-in-wordpress-2-9#comments</comments>
		<pubDate>Wed, 25 Nov 2009 02:05:41 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2216</guid>
		<description><![CDATA[How to add descriptions to individual widget areas in WordPress 2.9 and why this is a useful feature for end users.]]></description>
			<content:encoded><![CDATA[<p><span class="drop-cap">H</span>ave you ever used a WordPress theme with more than a couple of widget areas?  More specifically, have you ever used a WordPress theme with loads of widget areas and no idea how they all worked within the theme?</p>
<p>If you&#8217;ve ever used a theme of mine, you know I love adding widget areas everywhere. And, I know this can be confusing for some people.</p>
<p>Fortunately, WordPress 2.9 will allow theme developers to add a description for each widget area.  This should help end users figure out what the heck is going on.</p>
<h2>Widget descriptions from a user&#8217;s view</h2>
<p>If you&#8217;re an end user and your theme author has added descriptions, you&#8217;ll see the description near the top of the widget area on the <em>Widgets</em> admin screen.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2009/11/sidebar-descriptions.png" alt="Widget Area Descriptions" title="Widget Area Descriptions" width="600" height="428" class="aligncenter size-full wp-image-2217" /></p>
<h2>Adding descriptions to widget areas</h2>
<p>If you&#8217;re a theme developer, adding descriptions to your widget areas is as simple as adding an extra argument to the <code>register_sidebar()</code> function. Use the below <acronym title="Hypertext Preprocessor">PHP</acronym> code as a guide.</p>
<pre><code>add_action( 'init', 'register_my_widget_areas' );

function register_my_widget_areas() {

	register_sidebar( array(
		'name' => __('Primary', 'example'),
		'id' => 'primary',
		'description' => __('The main widget area, most often used as a sidebar.', 'example'),
		'before_widget' => '&lt;div id="%1$s" class="widget %2$s widget-%2$s">',
		'after_widget' => '&lt;/div>',
		'before_title' => '&lt;h3 class="widget-title">',
		'after_title' => '&lt;/h3>'
	) );
}</code></pre>
<p>The new code allowed in 2.9 is the <code>description</code> argument.</p>
<pre><code>'description' => __('The main widget area, most often used as a sidebar.', 'example'),</code></pre>
<p>Theme authors, it&#8217;s time to implement this new feature for your users.  It will take less than five minutes to add to your theme and should at least cut back on a few support queries.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2009/11/24/sidebar-widget-area-descriptions-in-wordpress-2-9/feed</wfw:commentRss>
		<slash:comments>58</slash:comments>
		</item>
		<item>
		<title>Everything you need to know about WordPress 2.9&#8242;s post image feature</title>
		<link>http://justintadlock.com/archives/2009/11/16/everything-you-need-to-know-about-wordpress-2-9s-post-image-feature</link>
		<comments>http://justintadlock.com/archives/2009/11/16/everything-you-need-to-know-about-wordpress-2-9s-post-image-feature#comments</comments>
		<pubDate>Mon, 16 Nov 2009 07:50:08 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Tutorials]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2126</guid>
		<description><![CDATA[An in-depth look at how the post image feature in WordPress 2.9 can be used from the perspective of both end users and developers.]]></description>
			<content:encoded><![CDATA[<p><span class="drop-cap">Y</span>ou may have heard a bit of news about a new thumbnail feature for themes coming to WordPress 2.9.  Yes, you&#8217;ll be able to easily upload a post thumbnail.  However, it&#8217;s not just thumbnails.  The image will have various sizes.  So, I&#8217;m going to refer to this feature as the post image feature.</p>
<p>In this tutorial, I&#8217;ll be covering the various things you can do with the post image feature.  Some things will be specific to end users while others will be useful for theme and plugin developers.</p>
<p>One important thing to note is that this new feature is an image-based representation of a post.  The image itself is directly tied to your post.  You shouldn&#8217;t think of it as something different than that.</p>
<h2>How does an end user make use of this feature?</h2>
<p>First, your theme must add support for it.  Otherwise, you won&#8217;t be able to use it.  At this point, let&#8217;s assume that your theme does support it.  I&#8217;ll go over instructions for theme authors later.</p>
<p>To use this feature, you must be within the post editing screen of your WordPress admin.  On this screen, you&#8217;ll see a new meta box labeled &#8220;Post thumbnail&#8221; (or &#8220;Page thumbnail&#8221; for pages).  There&#8217;ll be a link to &#8220;Set thumbnail,&#8221; which will allow you to use the media uploader to load a new image.</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2009/11/the-post-image.png" alt="Screenshot of WordPress 2.9's post image uploader" title="The Post Image" width="600" height="429" class="aligncenter size-full wp-image-2127" /></p>
<h2>It&#8217;s not just for thumbnails</h2>
<p>Even though it is called &#8220;post thumbnails,&#8221; we can technically use the feature for all sorts of things (e.g., feature images, medium-sized images for the front page, etc.).</p>
<p>By default, WordPress gives you several image sizes each time you upload an image.  These image sizes are:</p>
<ul>
<li>Thumbnail</li>
<li>Medium</li>
<li>Large</li>
<li>Full (the image you uploaded)</li>
</ul>
<p>Some plugins even extend this by allowing more intermediate sizes.  The important thing is that you understand that more than thumbnails can be used here.</p>
<h2>How to add support for the post image feature in a theme</h2>
<p>Theme authors, I&#8217;m going to make this simple for you.  You only need one line of code to turn this feature on for your users.  Add this to your theme&#8217;s <code>functions.php</code> file:</p>
<pre><code>add_theme_support( 'post-thumbnails' );</code></pre>
<p>Or, you can register support for specific post types.  For example, let&#8217;s suppose you wanted to add thumbnail support for both the <code>post</code> and <code>movie</code> post type but not for the <code>page</code> post type.  You&#8217;d use this instead:</p>
<pre><code>add_theme_support( 'post-thumbnails', array( 'post', 'page' ) );</code></pre>
<p>Of course, that one line doesn&#8217;t actually add anything to the front end for you.  You&#8217;ll need to call the image somewhere within The Loop in your template files.  For example, you might want to add thumbnails to your category archives.  You&#8217;d do this by adding this line of code:</p>
<pre><code>&lt;?php the_post_thumbnail( 'thumbnail' ); ?></code></pre>
<p>Or, maybe you have a section on a special template that calls for medium-sized images:</p>
<pre><code>&lt;?php the_post_thumbnail( 'medium' ); ?></code></pre>
<p>Or, a huge sliding feature area on your front page and need the full-sized image:</p>
<pre><code>&lt;?php the_post_thumbnail( 'full' ); ?></code></pre>
<p>That&#8217;s all there is to it.  As a theme author, you can hand over some powerful functionality to your users with just a couple of lines of code.</p>
<p>The rest of this tutorial will focus on developer features and some options for using older images.</p>
<h2>Checking if the post has an image</h2>
<p>Sometimes, you may need to check if a post has an image.  There&#8217;s a function for that called <code>has_post_thumbnail()</code>, which will return <code>true</code> or <code>false</code> based on whether there&#8217;s an image.</p>
<p>In this example, we&#8217;ll check if there&#8217;s an image.  If there&#8217;s not, we&#8217;ll show a default image instead.</p>
<pre><code>&lt;?php
	if ( has_post_thumbnail() )
		the_post_thumbnail( 'thumbnail' );
	else
		echo '&lt;img src="default-image.png" alt="Example Image" title="Example" />';
?></code></pre>
<h2>Getting the post image ID</h2>
<p>Maybe you need to write your own custom script but still want to allow users to upload their own images.  You can grab the post image ID and use it.  This ID is saved as the meta value for the meta key <code>_thumbnail_id</code>.  It is the ID of the attached file.</p>
<p>You only need to call the function in your code like so:</p>
<pre><code>$image_id = get_post_thumbnail_id();</code></pre>
<h2>How to return the image instead of displaying it</h2>
<p>In some scenarios, you might want to return the post image for use in your <acronym title="Hypertext Preprocessor">PHP</acronym> code instead of displaying it.</p>
<p>Here&#8217;s an example of that functionality:</p>
<pre><code>$image = get_the_post_thumbnail( $post->ID, 'thumbnail' );</code></pre>
<h2>How to filter the image size</h2>
<p>Some plugin developers may want to filter the image size (or maybe even child theme authors).  The <code>post_thumbnail_size</code> filter hook is available for that.  The filter function below is for changing the <code>thumbnail</code> size to <code>medium</code>.</p>
<p>Add this <acronym title="Hypertext Preprocessor">PHP</acronym> code to your theme&#8217;s <code>functions.php</code> file or your plugin file:</p>
<pre><code>add_filter( 'post_thumbnail_size', 'my_post_image_size' );

function my_post_image_size( $size ) {
	$size = 'medium';
	return $size;
}</code></pre>
<h2>Changing the <acronym title="Hypertext Markup Language">HTML</acronym> output of the post image</h2>
<p>There may be some scenarios where you&#8217;ll want to change the <acronym title="Hypertext Markup Language">HTML</acronym> markup of the displayed image.  In this example, I&#8217;ll show you how to wrap the image with a link to the post.</p>
<p>Add this <acronym title="Hypertext Preprocessor">PHP</acronym> code to your theme&#8217;s <code>functions.php</code> file or your plugin file:</p>
<pre><code>add_filter( 'post_thumbnail_html', 'my_post_image_html', 10, 3 );

function my_post_image_html( $html, $post_id, $post_image_id ) {

	$html = '&lt;a href="' . get_permalink( $post_id ) . '" title="' . esc_attr( get_post_field( 'post_title', $post_id ) ) . '">' . $html . '&lt;/a>';

	return $html;
}</code></pre>
<h2>What happens to my old images/thumbnails?</h2>
<p>If you&#8217;re like me and many others, you may have been using custom fields to add images to your posts for years.  If you switch to this new method, everything will be lost.</p>
<p>I&#8217;ve got a solution for this problem:  The <a href="http://wordpress.org/extend/plugins/get-the-image" title="Get the Image WordPress plugin">Get the Image</a> plugin.</p>
<p>Version 0.4 will be released when WordPress 2.9 is out.  Not only will support be added for the new WordPress post image feature, but you won&#8217;t lose all of the hard work you&#8217;ve put in.  The plugin will have the ability to check for post images in five different ways (in the below order):</p>
<ul>
<li>Custom fields.</li>
<li>New post image feature.</li>
<li>Attached image.</li>
<li>Scan the post for images.</li>
<li>Default image.</li>
</ul>
<p>For those of you already using this plugin or a theme of mine that includes the script, you&#8217;ll only have to upgrade the plugin or theme.  The feature will be turned on for you by default, so you will be able to start using the new feature without touching anything but an upgrade button.</p>
<h2>Have fun with your new post images</h2>
<p>I hope this tutorial has given you an in-depth look at the post image feature.  There are <a href="http://www.binarymoon.co.uk/2009/10/wordpress-the_post_image/" title="WordPress 2.9 &mdash; the_post_image">some limitations</a>, but on the whole, this feature will make things much easier for end users compared to the currently-available methods.</p>
<p>If you&#8217;re a user of my <a href="http://wordpress.org/extend/plugins/get-the-image" title="Get the Image WordPress plugin">Get the Image plugin</a> or <a href="http://themehybrid.com/themes/hybrid" title="Hybrid theme framework">Hybrid theme</a>, look out for an update within a few days of WordPress 2.9.  You&#8217;ll be able to start using the post image functionality soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2009/11/16/everything-you-need-to-know-about-wordpress-2-9s-post-image-feature/feed</wfw:commentRss>
		<slash:comments>173</slash:comments>
		</item>
	</channel>
</rss>
