<?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</title>
	<atom:link href="http://justintadlock.com/tags/wordpress/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>Realizing a dream: Writing a WordPress book</title>
		<link>http://justintadlock.com/archives/2010/09/01/realizing-a-dream-writing-a-wordpress-book</link>
		<comments>http://justintadlock.com/archives/2010/09/01/realizing-a-dream-writing-a-wordpress-book#comments</comments>
		<pubDate>Wed, 01 Sep 2010 14:03:59 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2538</guid>
		<description><![CDATA[My journey to become a published author and how the WordPress community has made this possible.]]></description>
			<content:encoded><![CDATA[<p class="alert">This is a story (the short version) of my personal journey to becoming an author.  Thank you to everyone in the WordPress community that has helped make this happen by allowing me to be a part of the community over the last few years.</p>
<h2>The early years</h2>
<p>As I was growing up in smalltown Alabama, I always wanted to be a writer.  From about the time I could hold a crayon, I was writing something.  Writing on the walls.  The kitchen table.  Occasionally, on paper.  From what my parents tell me, I could do this quite well at about the age of 3.</p>
<p>During my pre-teen years, I wanted to follow in my father&#8217;s footsteps and write songs, so music and lyrics were my first introduction to how beautiful language could be.</p>
<p>Eventually, I outgrew my songwriting phase.  Be glad I did.  The world certainly doesn&#8217;t need any more boy-band pop songs.  I figured I could offer something of a little more substance to the world.</p>
<h2>High school</h2>
<p>In high school, I had the most wonderful English teacher.  She was one of those teachers that understood that literacy is not just about basic reading and writing skills.  Literature.  Technology.  Music.  Film.  Those are the things that matter.  Don&#8217;t get me wrong.  We still had to do the boring high school English class stuff.  But, she opened my mind to the world outside of the small town I was living in.</p>
<p>At some point during my senior year I realized that I wanted to write.  I mean <em>really</em> write.  It was the first time I&#8217;d ever put &#8220;write a book&#8221; on my list of life goals.</p>
<h2>College</h2>
<p>I graduated from Auburn University in 2007 with a B.A. in English and a concentration in creative writing and journalism.</p>
<p>When I began college, I didn&#8217;t plan on having a degree in English.  I was in software engineering.  Then I was in hotel and restaurant management.  Then I was in software engineering again.  Like many other college students, I bounced around majors a few times.  It was tough finding something that was both enjoyable and challenging.</p>
<p>Despite protests from friends and a few from my family, I decided to take the plunge and declare myself as an English major.  What I found was something that I loved.  How could anyone <em>not</em> love reading 20+ books a semester?  I had the time of my life exploring ethnographic studies, novels, and even the Bible as literature.</p>
<p>Each professor impacted my life in some way.  Each class allowed me to explore other cultures.  Each friend I got to know, helped shape me.</p>
<p>By the time I graduated, I had narrowed my list of life goals down to a few things.  At the top of that list:  <em>Write something that has an impact on someone&#8217;s life</em>.</p>
<p>At some point during college, I also started learning <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheets">CSS</acronym>, <acronym title="Hypertext Preprocessor">PHP</acronym>, and WordPress.</p>
<h2>After college</h2>
<p>Harsh realization that life is not all roses and peaches.</p>
<p>&#8230;Time spent wandering the globe&#8230;</p>
<p>I moved back to Alabama last year because I wanted to get back to my roots.  I wanted to engulf myself in the white-trash, trailer-park, tobacco-chewing culture that I hadn&#8217;t been a part of in so long.</p>
<p>The plan:  Observe the culture.  Write.</p>
<p>I could give you at least 100 reasons why I haven&#8217;t finished a novel yet, but I won&#8217;t.  There&#8217;s no point in trying to justify losing sight of my goal.</p>
<p>I also spent some more time playing around with WordPress during this phase of my life.  I suppose that time could&#8217;ve been spent working on the great Southern American novel.</p>
<h2>An opportunity</h2>
<p>A few months ago, I received an email about collaborating on a WordPress plugin development book for <a href="http://www.wrox.com" title="Wrox">Wrox</a>, a company devoted to publishing books &#8220;by programmers for programmers.&#8221;</p>
<p>At first, I was a bit hesitant to take on any extra WordPress projects.  It also meant that I wouldn&#8217;t be able to apply for teaching jobs this school year, which was one of my <a href="http://justintadlock.com/archives/2010/02/01/2010" title="2010">goals for 2010</a>.  And, it wasn&#8217;t quite what I had in mind when I put &#8220;write a book&#8221; on my list of life goals.</p>
<p>However, it was an opportunity to write about something I&#8217;m passionate about.</p>
<h2>The book</h2>
<p>We have a great team of WordPress minds melding for what will be an awesome WordPress plugin development book.  <a href="http://strangework.com/" title="Brad Williams">Brad Williams</a>, <a href="http://planetozh.com/blog/" title="planetOzh">Ozh Richard</a>, and I are the writers.  We&#8217;ve also picked up <a href="http://www.andrewnacin.com/" title="Andrew Nacin">Andrew Nacin</a> as our WordPress technical editor.</p>
<p class="note">As a sidenote to this:  I&#8217;m convinced that Andrew is actually a super-advanced robot that has been programmed to do nothing other than write awesome WordPress code.  And, I&#8217;m happy to have him on the team.</p>
<p>I don&#8217;t want to get into too many technical details about the book yet.  I do want to say that it will be a great resource for professional plugin development.  We will put everything we have into making this the best book on creating plugins available for WordPress.</p>
<p>For me, this book announcement is mostly about sharing my personal journey to this point.  I am thankful that Wrox, Brad, and Ozh are giving me an opportunity to realize one of my lifelong dreams.  And, I hope that all my readers will come along on this journey with me (and buy the book when it&#8217;s published in March).</p>
<p>Also, check out theses posts by Brad and Ozh:</p>
<ul>
<li><a href="http://www.strangework.com/2010/09/01/new-book-professional-wordpress-plugin-development/" title="New Book: Professional WordPress Plugin Development!">New Book: Professional WordPress Plugin Development</a></li>
<li><a href="http://planetozh.com/blog/2010/09/into-plugins-you-will-love-this-plugindevbook/" title="Into Plugins?  You Will Love This.">Into Plugins?  You Will Love This.</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/09/01/realizing-a-dream-writing-a-wordpress-book/feed</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<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>Frameworks? Parent, child, and grandchild themes?</title>
		<link>http://justintadlock.com/archives/2010/08/16/frameworks-parent-child-and-grandchild-themes</link>
		<comments>http://justintadlock.com/archives/2010/08/16/frameworks-parent-child-and-grandchild-themes#comments</comments>
		<pubDate>Mon, 16 Aug 2010 17:05:49 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Discussion]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2517</guid>
		<description><![CDATA[Solving the big mystery of parent, child, and grandchild themes by explaining what theme frameworks really are.]]></description>
			<content:encoded><![CDATA[<p>One question that crops up every once in a while from my theme users is how to create a WordPress grandchild theme.  Most of the time, a user asks, &#8220;How do I update my child theme?  Do I need to create a grandchild theme?&#8221;</p>
<p>The idea of parent/child themes was created so that the parent theme could be updated while keeping customizations intact within a child theme.  That system works great.  The problems begin when a child theme is updated.  Users tend to want to take advantage of the update, but they can&#8217;t upgrade because they&#8217;ve made customizations. </p>
<p>Essentially, we&#8217;ve just added another layer to the preexisting problem.</p>
<p>But, that&#8217;s not where the <em>real</em> problem is at.  The problem is confusion over what frameworks, parent themes, and child themes are.  Users aren&#8217;t to blame for this confusion.  Theme developers are at fault here (even me), and I&#8217;m going to attempt to clear things up.</p>
<h2>Advanced parent themes are not frameworks</h2>
<p>I&#8217;m going to avoid calling any other &#8220;framework&#8221; themes out and tell you that my own <a href="http://themehybrid.com/themes/hybrid" title="Hybrid WordPress theme">Hybrid theme</a> is not a framework, at least not in the traditional development framework sense.  It&#8217;s an advanced parent theme.  Admittedly, I&#8217;ve called it a &#8220;framework&#8221; before because I&#8217;ve just been following the crowd.</p>
<p>What should we call the <em>Hybrid</em> theme?  Simple.  It&#8217;s a parent theme.</p>
<p>One thing we should definitely not confuse are the terms &#8220;framework&#8221; and &#8220;parent theme.&#8221;  These two are not interchangeable.  That&#8217;s where a lot of the confusion stems from.</p>
<h2>What is a theme framework?</h2>
<p class="note">This is the question I most wanted to answer because I&#8217;ll be releasing a framework for theme developers soon (see below).  But, I can&#8217;t do that with all this confusion floating around the community.</p>
<p>A theme framework is a set of conventions to use for developing WordPress [parent] themes.</p>
<p>Yes, that&#8217;s a bit vague, but frameworks can exist for all kinds of different purposes.  This can be something like an elegant template engine (<a href="http://carringtontheme.com/" title="Carrington Theme Framework">Carrington Core</a> is really good for this) or a set of helper functions for more quickly building a theme.</p>
<p>It is not a theme though.  You can&#8217;t simply drop it in your WordPress themes directory and expect it to work.</p>
<p>Frameworks are for theme developers.  They offer a set of standards (or whatever features) for theme developers to use in creating their own themes.  They&#8217;re a set of functions/features created to aid development.</p>
<h2>What is a parent theme?</h2>
<p>Nearly all WordPress themes are parent themes.  Only those called &#8220;child themes&#8221; are not parent themes.</p>
<p>Theme developers create parent themes for users to download and install on their sites.  My <em>Hybrid</em> theme is, without a doubt, a parent theme.  Parent themes should house the theme design, functionality, and the templates required for running the theme in WordPress.</p>
<p>You can use a framework to build a parent theme, but the framework is not a parent theme itself.</p>
<h2>What is a child theme?</h2>
<p>A child theme is something users should be creating so that they can customize the look and functionality of their site.  The child theme inherits all of its functionality from a single parent theme.</p>
<p>When a theme developer creates a child theme, things become problematic because that child theme might eventually need an update.  If you&#8217;re a theme developer and are building a child theme with a 20kb functions file and five or six custom templates, I can assure you that you&#8217;re doing it wrong.  I&#8217;ve even had to tell myself this.</p>
<p>What you should really be creating is a parent theme.  Child themes from theme developers should be nothing more than a stylesheet and a few functions.  This idea of releasing advanced child themes just creates the same problem child themes were meant to solve: <em>upgradability</em>.</p>
<p>I&#8217;ve got over two years of experience at this point in dealing with parent/child themes if you need a reason to take my advice on this.</p>
<h2>How frameworks work</h2>
<p><em>Confused yet?</em>  Let me break this process down for you and explain how it <em>should</em> work.</p>
<ul>
<li>Frameworks come packaged within a single folder.</li>
<li>Developers drop the framework folder into a new parent theme and load the framework.</li>
<li>Users create a child theme based on the parent theme to house their customizations, allowing both the framework and parent theme to be updated.</li>
</ul>
<p>Here&#8217;s a diagram for reference:</p>
<p><img src="http://justintadlock.com/blog/wp-content/uploads/2010/08/framework-parent-child.png" alt="Theme structure when using a framework, parent theme, and child theme" title="Framework theme structure" width="600" height="485" class="aligncenter size-full wp-image-2521" /></p>
<p>Users should only ever have to worry about creating a child theme.  This will allow them to make modifications without losing them when the parent theme is updated.  They shouldn&#8217;t have to worry about all the other stuff.</p>
<p>As you can see by now (I hope), the question of grandchild themes has been completely averted because theme developers shouldn&#8217;t be adding advanced functionality (that might need future updating) within child themes.</p>
<h2>Doesn&#8217;t Hybrid break these rules?</h2>
<p>The <em>Hybrid</em> parent theme doesn&#8217;t break the rules.  A couple of the child themes?  Definitely.  If I could afford a time-traveling machine (and if they existed), I&#8217;d zip back a year or two and turn a couple of those child themes into parent themes instead.  We all have to learn from our mistakes, and I can freely admit that I&#8217;ve taken the wrong route on occasion.</p>
<p>So, I&#8217;m going to give you a real-world example of everything I&#8217;ve been talking about and how it could&#8217;ve been avoided with one of my own themes.</p>
<p><em>Hybrid</em> has a child theme called <a href="http://themehybrid.com/themes/hybrid-news" title="Hybrid News WordPress theme">Hybrid News</a>.  This child theme has a few extra features that make it more advanced than its parent theme.  One good example of a problem was when WordPress 3.0 launched with a new <a href="http://justintadlock.com/archives/2010/06/01/goodbye-headaches-hello-menus" title="Goodbye, headaches. Hello, menus!">menu system</a> (which I love).  The <em>Hybrid News</em> child theme has an extra navigation menu that&#8217;s not present within its parent theme.</p>
<p>The problem:  How do you upgrade the <em>Hybrid News</em> child theme to use the the new nav menu system for its extra menu?</p>
<p>You certainly can&#8217;t expect users to upgrade the child theme and lose all of their customizations.  To solve this particular problem, I wrote a tutorial on making the switch to the new system.  But, it was just a way to avoid the larger problem at hand.</p>
<p>The solution should&#8217;ve been:  Make <em>Hybrid News</em> a parent theme.  This would allow it to be upgraded and users to keep their customizations intact.</p>
<p>If you&#8217;re a theme developer with a lot of advanced child themes, you may be thinking that you&#8217;ve got this problem all figured out.  You may have already come up with plenty of nifty solutions for avoiding these types of problems.  But, no one can foresee what new things will come in later versions of WordPress to conflict with those solutions.</p>
<h2>Introducing Hybrid Core: A theme framework</h2>
<p>Last year, I mentioned that I&#8217;d <a href="http://themehybrid.com/archives/2009/11/whats-in-store-for-hybrid-0-7" title="What's in store for Hybrid 0.7">release Hybrid Core</a> to the public for download.  Unfortunately, that release never came out.  I wanted some more time to perfect it, which turned out to be around a year worth of extra time.</p>
<p><em>Hybrid Core</em> will be a theme development framework for use by other theme developers.  What this means is that any theme developer will be able to download this and build parent themes with an awesome framework behind them.  Yes, I&#8217;m essentially giving you the keys to the <a href="http://themehybrid.com" title="Theme Hybrid">Theme Hybrid</a> kingdom.</p>
<p><em>Hybrid Core</em> is currently packaged within my <em>Hybrid</em> parent theme.  It is used to handle the &#8220;logic&#8221; behind how the theme runs.  Theme developers will be able to load this framework and build themes using the set of conventions provided by the framework.  All of the <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheets">CSS</acronym>, and extra functionality will be left up to you. </p>
<p>In the next month or two, I&#8217;ll be putting the finishing touches on this.  I&#8217;m still moving some stuff around that&#8217;s specific to the <em>Hybrid</em> parent theme and getting it out of the way.</p>
<p>It&#8217;d be awesome to see many great themes built off this framework.  It&#8217;s a project that I started building in June 2008, so a lot of work and testing have been put into it.  The next theme I build will be a parent theme based off it, so you&#8217;ll have a good, working example of how to use the framework.</p>
<p class="alert">Just in case you were wondering if building a &#8220;grandchild&#8221; theme is actually possible, the answer is no, at least not by default.  And, I hope to never see the day it happens.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/08/16/frameworks-parent-child-and-grandchild-themes/feed</wfw:commentRss>
		<slash:comments>68</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>A WordPress forum plugin using custom post types</title>
		<link>http://justintadlock.com/archives/2010/07/16/a-wordpress-forum-plugin-using-custom-post-types</link>
		<comments>http://justintadlock.com/archives/2010/07/16/a-wordpress-forum-plugin-using-custom-post-types#comments</comments>
		<pubDate>Fri, 16 Jul 2010 12:27:46 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Plugins]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2474</guid>
		<description><![CDATA[How I'm using custom post types and taxonomies to create a forum plugin that integrates full into WordPress.]]></description>
			<content:encoded><![CDATA[<p><a href="http://popcritics.com/forums" title="Pop Critics forums"><img src="http://justintadlock.com/blog/wp-content/uploads/2010/07/pop-critics-forums-300x356.png" alt="Example screenshot of a WordPress forum plugin" title="Forums plugin example" width="300" height="356" class="alignright size-medium wp-image-2476" /></a></p>
<p>I&#8217;ve been promising a real-world example of what&#8217;s possible with custom post types for a while.  But, I didn&#8217;t want to put together <em>yet-another-long-technically-detailed</em> post.  I wanted to give you something that would open your mind to the possibilities.</p>
<p>And, there&#8217;s loads of possibilities.</p>
<p>I&#8217;ve been tinkering around with the idea of building a forum plugin, so I decided to get behind the project completely and make it happen.  What started out as a simple project quickly turned into something that a lot of people have been wanting &mdash; a forum plugin that fully integrates itself within WordPress.</p>
<h2>Post types for the plugin</h2>
<p>The plugin uses three post types for handling the structure:</p>
<ul>
<li><strong>Forums:</strong> This is your top level, which holds everything else.</li>
<li><strong>Topics:</strong> Children of forums and use the topic tags taxonomy.</li>
<li><strong>Replies:</strong> These are the individual posts made within a topic.</li>
</ul>
<p>I had originally taken a different route of using a forum taxonomy, topic post type, and reply comment type.  However, using that structure had major limitations.</p>
<p>The benefits of using three post types are numerous.  Here are some examples:</p>
<ul>
<li>Forums can have metadata (custom fields) and media attachments added to them to allow a lot of cool stuff (forum thumbnails, for example).</li>
<li>You get pretty permalinks using a reply post type (<code>forums/topic-name/page/2</code>).</li>
<li>Replies can also have their own media attachments (user-uploaded images).</li>
<li>Capabilities/permissions are handled a lot better with post types.</li>
<li>Can set up custom post statuses such as &#8220;closed&#8221; and use the current statuses like &#8220;private.&#8221;</li>
<li>Works well with plugins that allow you to edit from the front end of the site.</li>
</ul>
<p>This is not to say there aren&#8217;t issues with this method.  There&#8217;s a lot of custom work work that needed to be done, which isn&#8217;t surprising considering I&#8217;m using <em>custom</em> post types.</p>
<p class="note">I can&#8217;t take all the credit for this idea of using three post types.  <a href="http://johnjamesjacoby.com" title="John James Jacoby">John James Jacoby</a> convinced me this was the best route to go.</p>
<h2>Taxonomies for the plugin</h2>
<p>The only taxonomy used by default is the topic tag taxonomy.  It allows users to assign tags to specific topics.</p>
<p>The great thing about the plugin though is that you can build custom taxonomies on top of it.  You can give forums, topics, and replies their own taxonomies if you wanted.  Since we&#8217;re using custom post types for those things, the possibilities are endless.</p>
<h2>Integration with WordPress</h2>
<p>Obviously, we want our forum plugin to work well with WordPress.  Some of the current problems users of other forum software are facing when integrating are:</p>
<ul>
<li>Separate user login pages (and separate user database tables in some cases).</li>
<li>Separate roles and permissions setups.</li>
<li>Using multiple themes to get the same design across the site.</li>
<li>Not being able to use WordPress plugins within the forum.</li>
<li>Having to figure out how &#8220;deep integration&#8221; works just to use things like menus and widgets.</li>
</ul>
<p>My plugin seeks to solve those issues and use the tools available in WordPress.</p>
<h2>Lightweight</h2>
<p>I&#8217;m not a fan of adding every fancy gizmo and gadget in the world to a forum.  I like to keep things simple and extend it with other plugins when I need a new feature.  I also don&#8217;t want 20 theme templates when I can use a handful.</p>
<p>The biggest goal I have is to keep this thing as lightweight as possible.  There are over 10,000 plugins for WordPress that will allow this plugin to be extended.</p>
<h2>What about the bbPress plugin?</h2>
<p>While this is outside the scope of what I&#8217;d planned on writing about, I know questions about bbPress will crop up.  I&#8217;ll try to address those.</p>
<p>It&#8217;s true that bbPress will be <a href="http://bbpress.org/forums/topic/bbpress-plugin-is-born" title="bbPress plugin is born">becoming a plugin</a> in the future and work has already started on it.  I&#8217;m happy that there&#8217;s at least something happening.  I love bbPress and have been using it for years, but I can&#8217;t wait around six or seven months again to see where the project is headed.  I&#8217;m not saying bbPress isn&#8217;t going anywhere, but I had to make the decision to move forward on my own after the last disappointment.</p>
<p>I&#8217;d love to be involved in the bbPress plugin project at some point, but my priorities right now don&#8217;t mesh well with it.  It&#8217;d also be great if the ideas used in my plugin or any of its code gets used in the bbPress plugin.</p>
<p>One thing I will promise to plugin users is that I&#8217;ll try to make it as easy as possible to switch between either plugin if that&#8217;s what they choose to do.</p>
<h2>Demo and testing</h2>
<p>The plugin isn&#8217;t ready for a public release right now.  There&#8217;s tons of work still ahead.  But, testing does need to be done on a large enough scale for me to make this a solid plugin.</p>
<p>I&#8217;ve put the plugin on one of my own sites for live testing.  If you have any interest in this plugin at all or just want to help test, please register for my <a href="http://popcritics.com/forums" title="Pop Critics forums">forums at Pop Critics</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/07/16/a-wordpress-forum-plugin-using-custom-post-types/feed</wfw:commentRss>
		<slash:comments>102</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>Lowercase p, dangit!</title>
		<link>http://justintadlock.com/archives/2010/07/08/lowercase-p-dangit</link>
		<comments>http://justintadlock.com/archives/2010/07/08/lowercase-p-dangit#comments</comments>
		<pubDate>Thu, 08 Jul 2010 07:39:20 +0000</pubDate>
		<dc:creator>Justin Tadlock</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Discussion]]></category>

		<guid isPermaLink="false">http://justintadlock.com/?p=2443</guid>
		<description><![CDATA[Why the <code>capital_P_dangit()</code> function is not only a bug but a detrimental blow to the WordPress community.]]></description>
			<content:encoded><![CDATA[<p>If you haven&#8217;t been following the latest hot debate in the WordPress community, you&#8217;re in for some news.  If you have been following it, you&#8217;re probably in a fiery rage, given up all hope in the &#8220;community&#8221; aspect of this community project, or are just sitting back laughing at the rest of us.</p>
<p><em>The issue</em>:  Before WordPress 3.0 was released, a small piece of code was added to the WordPress core that changes all instances of &#8220;Wordpress&#8221; (notice the lowercase &#8220;p&#8221;) to &#8220;WordPress&#8221; in areas where content is shown on the site.  We&#8217;ll get to the details in a bit.</p>
<p>I tried hard to stay out this debate because I&#8217;m fairly certain I made a vow to myself to stay out of these types of arguments.  But, I&#8217;ve got a few opinions on this one that I can&#8217;t just keep to myself.  And, as someone that is considered a <em>leader</em> within the WordPress community, I feel responsible for communicating with that community on this issue.</p>
<h2>It&#8217;s spelled &#8220;WordPress&#8221;</h2>
<p><a href="http://wpcamelcase.com/" title="WP CamelCase">WPCamelCase.com</a> says so, and I&#8217;d never question an entire site dedicated to the proper spelling of a single word.</p>
<p>On a more serious note, these are not proper:</p>
<ul>
<li>Wordpress</li>
<li>wordPress</li>
<li>wordpress</li>
<li>Word Press</li>
<li>word press</li>
<li>wordress</li>
<li>WoRdPrEsS</li>
</ul>
<p>Coming from an English and journalism (especially journalism) background, I feel a strong need to hack into the site of anyone that misspells WordPress and correct it for them.  Fortunately, I don&#8217;t know how to hack people&#8217;s sites, have just a smidgen of self control, and respect the rights of others.</p>
<h2>Why is there an issue?</h2>
<p>Matt Mullenweg wrote a filter function called <code>capital_P_dangit()</code> that correctly capitalizes the &#8220;P&#8221; in misspellings of WordPress where the &#8220;p&#8221; is lowercase.  It may seem like a minor thing, but there are several issues at hand.</p>
<ul>
<li>The code literally breaks things like URLs on some sites.  For example, suppose you installed WordPress in a <code>/Wordpress</code> directory.  That would cause all kinds of trouble with things like images.</li>
<li>This function is effectively changing what people write, and WordPress should not have editorial control over the content of anyone&#8217;s blog.</li>
<li>The code was <a href="http://core.trac.wordpress.org/changeset/14996" title="WordPress changeset: 14996">committed to WordPress</a> without a Trac ticket, so it wasn&#8217;t left open to community discussion beforehand.</li>
<li>Matt&#8217;s responses seem to dismiss the very community of people that help make WordPress what it is.</li>
</ul>
<h2>Following the discussion</h2>
<p>I cannot accurately represent all of the discussion that has happened to this point.  I highly recommend that you read the discussions provided by the below links if you want all the details.</p>
<ul>
<li><a href="http://core.trac.wordpress.org/ticket/13971" title="'Wordpress' being turned into CamelCase 'WordPress' breaks URLs">&#8220;Wordpress&#8221; being turned into CamelCase &#8220;WordPress&#8221; breaks URLs</a></li>
<li><a href="http://lists.automattic.com/pipermail/wp-hackers/2010-July/thread.html#32841" title="WP Hackers: July 2010: Putting the P in WordPress">Putting the P in WordPress: WP Hackers</a></li>
<li><a href="http://www.wptavern.com/automatically-correcting-the-wordpress-mistake" title="Automatically Correcting the WordPress Mistake">Automatically Correcting the WordPress Mistake</a></li>
<li><a href="http://www.wptavern.com/forum/general-wordpress/1745-wordpress-wordpress-core.html" title="Wordpress to WordPress in core?">Wordpress -> WordPress in core?</a></li>
<li><a href="http://hakre.wordpress.com/2010/07/07/wordpress-egomania/" title="MattPress Egomania">MattPress Egomania</a></li>
<li><a href="http://tomlany.net/2010/05/wordpress-to-wordpress/" title="Wordpress to WordPress">&#8220;Wordpress&#8221; to &#8220;WordPress&#8221; filter</a></li>
<li><a href="http://www.misthaven.org.uk/blog/2010/07/07/a-fuss-about-nothing/" title="A Fuss About Nothing">A Fuss About Nothing</a></li>
<li><a href="http://capitalp.org" title="The capital 'P' in WordPress caused the BP oil spill">CapitalP.org</a></li>
</ul>
<h2>Breaking URLs</h2>
<p>If nothing else, this issue must be addressed.  In fact, this bug was brought up in a <a href="http://core.trac.wordpress.org/ticket/13583" title="WordPress make WP contribute to drill baby drill">bug report</a> <em>before</em> WordPress 3.0 was released.  Yes, before.</p>
<p>The resolution set for this bug: <em>wontfix</em>.</p>
<p>A <a href="http://core.trac.wordpress.org/ticket/13971" title="'Wordpress' being turned into CamelCase 'WordPress' breaks URLs">new ticket</a> is now open for discussion and resolutions.  Mark Jaquith has at least created a patch that should fix this issue.</p>
<h2>Don&#8217;t change my content</h2>
<p>The <em>real</em> issue is not the bug; it&#8217;s the display of content that people didn&#8217;t write.  Sure, the cases where people actually intend to misspell WordPress are rare, but that&#8217;s besides the point.</p>
<p>The point is that the content is yours, and you should be able to write anything any way you see fit, including &#8220;WordPress.&#8221;</p>
<p>If you want to debate that last statement in any way, I suppose you can try all you want, but I can&#8217;t think of a single reason why a piece of software should be able to control the output of my words without consent.</p>
<p>We&#8217;re talking about principles here, and changing what people write in this manner goes against everything I believe in.  I simply refuse to allow this on my site.</p>
<p>One of the reasons I use WordPress is because of its philosophy on community, openness, and freedom, which fits along nicely with my own personal philosophy about most things in life.  The idea that a piece of software could infringe upon those values is what bothers people.</p>
<h2>What about emoticons and auto-paragraphs?</h2>
<p><em>What about apples and oranges?</em></p>
<p>This line of <em>reasoning</em> keeps getting brought up in the debate.</p>
<p>If you think the forced spelling of a word and the opt-in process of converting smileys and basic word-processing are one in the same, there&#8217;s no convincing you there&#8217;s an issue.  You may as well stop reading now.</p>
<h2>Why don&#8217;t you build a plugin?</h2>
<p>According to Matt Mullenweg, <a href="http://lists.automattic.com/pipermail/wp-hackers/2010-July/032900.html" title="WP Hackers July 2010: 032900">a plugin should be built</a>:</p>
<blockquote><p>
As I said before, you are in /complete control/ of your site. It&#8217;s a single line to remove a filter. If you don&#8217;t like the filter, vote with your feet or with a plugin.
</p></blockquote>
<p><em>Vote with your feet?</em>  This type of remark represents one of the biggest issues in the WordPress community.  Attitudes like this can bring down entire empires.</p>
<p>I completely agree with the plugin idea though.  Building plugins to gauge community interest in certain features and making the decision to include these plugins in core code based on statistics is a great idea.</p>
<p>As <a href="http://www.wptavern.com/automatically-correcting-the-wordpress-mistake" title="Automatically correcting the WordPress mistake">pointed out</a> by Jeff Chander, it just so happens that someone made a plugin nearly three years ago that does the same job as <code>capital_P_dangit()</code>.  It&#8217;s called <a href="http://wordpress.org/extend/plugins/ozhs-correctly-spell-wordpress/" title="Ozh' Correctly Spell WordPress plugin">Ozh&#8217; Correctly Spell WordPress</a>.</p>
<p>At the time of writing, this plugin has received a grand total of&#8230;wait for it&#8230;338 downloads!</p>
<p>As flawed as that argument is, a new plugin has been created called <a href="http://wordpress.org/extend/plugins/remove-wordpress-to-wordpress-filter" title="Remove Wordpress to WordPress Filter plugin">Remove Wordpress to WordPress Filter</a>  that disables the <code>capital_P_dangit()</code> functionality.  Funnily enough, its number of downloads will likely surpass the other plugin within a week or two given its current rate of adoption.</p>
<p>But, since we&#8217;re voting with plugins, there&#8217;ll be <a href="http://wordpress.org/extend/plugins/profile/greenshady" title="Justin Tadlock's plugins">16 other plugins</a> that will disable this filter soon enough.  All of my plugins will have this bug fix added to them in their next updates.</p>
<p>There&#8217;s two things that will make me reconsider this decision and remove this from my plugins:</p>
<ul>
<li>The <code>capital_P_dangit()</code> function is removed from the default filters or made to be opt-in.</li>
<li>An outcry of arguments from my plugin users to remove it.  Some of us <em>listen</em> to our users, even when we disagree with them.</li>
</ul>
<p class="alert">Since some folks have missed the point of this last argument, which I thought was clever (though I&#8217;m a bit biased), I must inject a note here to interrupt the flow of this article.  <strong>No</strong>, I don&#8217;t actually intend to update all 16 of my plugins to try and prove a point.  The entire point is to show how irrational such an action would be.</p>
<h2>How to remove the capital_P_dangit() filter</h2>
<p>You can either install the <a href="http://wordpress.org/extend/plugins/remove-wordpress-to-wordpress-filter" title="Remove Wordpress to WordPress Filter plugin">Remove Wordpress to WordPress Filter</a> plugin or add the below code to your theme&#8217;s <code>functions.php</code> file.</p>
<pre><code>remove_filter( 'the_content', 'capital_P_dangit' );
remove_filter( 'the_title', 'capital_P_dangit' );
remove_filter( 'comment_text', 'capital_P_dangit' );</code></pre>
<h2>Listen to your community</h2>
<p>I&#8217;ve only seen a handful of people that agree this function should be in WordPress.  It has been met with harsh opposition.  The people arguing to remove this function are people we need in the community.  They&#8217;re plugin developers, theme developers, contributors to core code, and evangelists for the WordPress platform.  These are the people that continue making WordPress better.</p>
<p>Don&#8217;t alienate them.</p>
<p>Are these people only a vocal minority of WordPress users?  Certainly.  However, these people speak for a larger amount of users.  For users without the knowledge of mailing lists.  For users without the understanding of how Trac works.  They are the people that interact with the majority every day.  They are the voice of the majority.</p>
<p>Don&#8217;t let their voices go unheard.</p>
]]></content:encoded>
			<wfw:commentRss>http://justintadlock.com/archives/2010/07/08/lowercase-p-dangit/feed</wfw:commentRss>
		<slash:comments>106</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>
	</channel>
</rss>
