Ever wanted to filter a query_posts call by template? If you're reading this post, you probably have or need to right now. You probably went to the query_posts documentation and scanned for something like "template=foo" and were deeply disappointed. Then maybe, in an act of desperation, you started to trudge around the plugin library. Stop! Stop right there! You don't need a plugin to do this. Everything you need is already in WordPress.

Let's start with a question: how does WordPress associate templates? The answer: as a secret custom field. What's a custom field, you ask? They're those useful little suckers under the content area in the WP editor:

But if the template is a custom field, you ask, then how come I don't see it down there? Well, I just said they're secret. After poking around WP database, I discovered the template for a page is determined by the custom field name _wp_page_template. My suspicion is that anything with the prefix _wp is hidden from the WP admin area and therefore secret.

Harnessing the awesome power of custom fields

On the bright side, even if you can't see the _wp_page_template in the custom fields area, I can assure you it's still there. And if it's there, you can use it in any of your nefarious schemes.

Query_posts provides 3 parameters relating to custom fields: meta_key, meta_value, and meta_compare. With those in mind, imagine you have a template called Profile (profile.php), and you want to exclude any page that is a Profile from our query. In order to do that, you'd would make a query_posts call like so:

query_posts(array(
    'post_type' => 'page',
    'meta_key' => '_wp_page_template',
    'meta_value' => 'profile.php',
    'meta_compare' => '!='
));

The main thing to note here is that the template is identified by the name of the PHP file (profile.php) and not by the the name of template (Profile).

Wrap-up

Filtering your query_posts query by template is as easy as filtering by any custom field. No plugin required. Just remember: use the PHP file name as the template identifier, not the template name.