Query Custom Post Types with Taxonomies

Query Custom Post Types with Taxonomies

Want to organize WordPress content effectively? Combine custom post types with taxonomies.

Custom post types let you create specialized content types like products, events, or real estate listings. Taxonomies group this content, like categorizing movies by genre or products by brand. Together, they enable powerful filtering and queries, improving content management and user navigation.

Key Takeaways:

  • Custom Post Types: Tailored content structures beyond default posts and pages.
  • Taxonomies: Organize content with categories or tags, including custom ones.
  • Combining Both: Enables advanced queries like "all action movies" or "products under $500."

Learn how to set up, register, and query them using PHP or plugins like CPT UI. Use WP_Query to create filters by single or multiple taxonomy terms, set conditions, and refine your queries for better results. This approach is ideal for creating dynamic websites like eCommerce stores, event directories, or content hubs.

Want to dive deeper? The article explores code examples, troubleshooting tips, and advanced techniques for combining taxonomy and meta queries.

#3: Querying Custom Post Type & Attachment Post Type data for the Front-end

Setting Up Custom Post Types and Taxonomies

To query custom post types by taxonomy, you first need to register both. This involves adding PHP code either to a custom plugin or the functions.php file of your theme. Using a plugin is a smart choice, especially for developers in the U.S. managing client websites or production environments, as it ensures your setup remains intact even if the theme changes.

How to Register Custom Post Types

To create a custom post type, you’ll use the register_post_type() function, hooked to WordPress’s init action. Let’s look at an example: registering a "Movies" custom post type, which is perfect for projects like film review sites, product directories, or event listings.

Here’s the code to set up the "Movies" post type:

function wpw_register_movie_cpt() {     $labels = array(         'name'               => 'Movies',         'singular_name'      => 'Movie',         'add_new'            => 'Add New',         'add_new_item'       => 'Add New Movie',         'edit_item'          => 'Edit Movie',         'new_item'           => 'New Movie',         'view_item'          => 'View Movie',         'search_items'       => 'Search Movies',         'not_found'          => 'No movies found',         'not_found_in_trash' => 'No movies found in Trash',         'all_items'          => 'All Movies',     );     $args = array(         'labels'             => $labels,         'public'             => true,         'has_archive'        => true,         'show_in_rest'       => true,         'menu_position'      => 5,         'menu_icon'          => 'dashicons-video-alt2',         'supports'           => array( 'title', 'editor', 'thumbnail', 'excerpt' ),         'rewrite'            => array( 'slug' => 'movies' ),     );     register_post_type( 'movie', $args ); } add_action( 'init', 'wpw_register_movie_cpt' ); 

In this setup:

  • 'public' => true ensures the post type is visible on the front end and can be queried with WP_Query.
  • 'has_archive' => true creates an archive page at /movies/, which can be filtered by taxonomy terms later.
  • 'show_in_rest' => true enables compatibility with Gutenberg and REST API queries.

After adding the code, visit Settings → Permalinks in your WordPress admin panel and click "Save Changes." This step flushes the permalinks, preventing 404 errors on your new archive pages.

How to Create Custom Taxonomies

Once your custom post type is set up, you’ll need a taxonomy to organize it. For the Movies example, let’s create a hierarchical "Genre" taxonomy, which works like categories, supporting parent-child relationships (e.g., Action, Comedy, Drama).

Here’s the code to register the Genre taxonomy and link it to the Movies post type:

function wpw_register_genre_taxonomy() {     $labels = array(         'name'              => 'Genres',         'singular_name'     => 'Genre',         'search_items'      => 'Search Genres',         'all_items'         => 'All Genres',         'parent_item'       => 'Parent Genre',         'parent_item_colon' => 'Parent Genre:',         'edit_item'         => 'Edit Genre',         'update_item'       => 'Update Genre',         'add_new_item'      => 'Add New Genre',         'new_item_name'     => 'New Genre Name',         'menu_name'         => 'Genres',     );     $args = array(         'labels'            => $labels,         'public'            => true,         'hierarchical'      => true,         'show_admin_column' => true,         'show_in_rest'      => true,         'rewrite'           => array( 'slug' => 'genre' ),     );     register_taxonomy( 'genre', array( 'movie' ), $args ); } add_action( 'init', 'wpw_register_genre_taxonomy' ); 

This code links the "Genre" taxonomy to the "Movies" post type using the second parameter: array( 'movie' ). You can attach the taxonomy to multiple post types if needed. The 'show_admin_column' => true option adds a "Genre" column to the Movies admin list, making it easier to filter posts by taxonomy terms.

To ensure smooth queries:

  • Use consistent slugs for taxonomies to avoid mismatches.
  • Match field types in queries (e.g., use term slugs with field => 'slug' or term IDs with field => 'term_id').
  • Assign terms to posts; untagged posts won’t appear in taxonomy-based queries.

With your custom post types and taxonomies in place, you’re ready to query them effectively.

Using Plugins for Setup

Prefer a no-code approach? Plugins like Custom Post Type UI (CPT UI) let you create custom post types and taxonomies through an easy-to-use admin interface. After installing CPT UI:

  1. Navigate to Add/Edit Post Types in your dashboard.
  2. Enter "movie" as the post type slug.
  3. Configure the labels and settings, ensuring "Has Archive" and "Show in REST" are enabled.
  4. Save your changes.

Next, go to Add/Edit Taxonomies, create a "genre" taxonomy, set it to hierarchical, and attach it to the "movie" post type.

CPT UI handles the same arguments you’d define in code, such as public, has_archive, and show_admin_column. This approach is great for prototyping or handing off projects to clients, especially when paired with resources like WP Winners, which offers tutorials and optimization tips.

Whether you set everything up with code or a plugin, your custom post types and taxonomies will be ready for querying. Up next: how to use WP_Query to filter by single taxonomy terms, using the Movies and Genre example as a foundation.

Querying Custom Post Types with a Single Taxonomy Term

Once your custom post types and taxonomies are set up, you can easily query posts based on specific taxonomy terms. To do this, you’ll use the tax_query parameter in WP_Query. This approach works seamlessly with any custom post type.

Basic WP_Query Structure for Taxonomy Queries

Here’s a simple example of how to retrieve posts from the "Movies" custom post type that belong to the "action" genre:

$args = array(     'post_type' => 'movie',     'tax_query' => array(         array(             'taxonomy' => 'genre',  // Taxonomy name             'field'    => 'slug',   // Field to match (slug, term_id, or name)             'terms'    => 'action', // Term to filter by         ),     ), ); $query = new WP_Query( $args );  if ( $query->have_posts() ) {     while ( $query->have_posts() ) {         $query->the_post();         echo '<h3>' . get_the_title() . '</h3>';     }     wp_reset_postdata(); } else {     echo 'No action movies found.'; } 

This code fetches all posts from the "Movies" post type that are tagged with the "action" genre. The tax_query parameter takes an array of conditions, where each condition specifies the taxonomy, the field to match, and the term to filter by.

Using Taxonomy Slugs vs. Term IDs

When querying taxonomy terms, you can choose between slugs (like "action") and term IDs (e.g., 45). Each has its advantages:

  • Slugs: These are human-readable, making them easier to use and maintain in your code, especially when hardcoding queries or working with URLs.
  • Term IDs: These are numeric identifiers assigned by WordPress. They’re useful for precise queries but require you to know the exact ID of the term.

Here’s the same query as above, but using a term ID instead of a slug:

$args = array(     'post_type' => 'movie',     'tax_query' => array(         array(             'taxonomy' => 'genre',             'field'    => 'term_id',             'terms'    => 45,         ),     ), ); $query = new WP_Query( $args ); 

Both approaches work, so choose the one that best suits your needs – slugs for readability, term IDs for precision.

Understanding the Field Parameter

The field parameter in tax_query determines how WordPress matches the taxonomy term. Here’s a breakdown of the common options:

Field Type When to Use Example
'slug' Best for readable, maintainable code 'field' => 'slug', 'terms' => 'action'
'term_id' Ideal for precise matching when slugs might change 'field' => 'term_id', 'terms' => 45
'name' Use for exact term name matches (case-sensitive) 'field' => 'name', 'terms' => 'Action Movies'

It’s important to ensure the field type aligns with the term you’re filtering by. For example, using term_id when you only know the slug will result in no matches. While the 'name' option is available, it’s less commonly used because it requires an exact match, including capitalization and spaces. Most developers prefer slugs for simplicity or term IDs for accuracy.

Querying with Multiple Terms and Taxonomies

After mastering single-term queries, it’s time to step up your filtering game by combining multiple terms or taxonomies. This approach is perfect for creating advanced filters in eCommerce catalogs, directories, or course listings. Let’s dive into how you can query multiple terms within a single taxonomy and expand to multiple taxonomies.

Querying Multiple Terms in One Taxonomy

To filter posts by several terms within the same taxonomy, you can pass an array to the terms parameter. For example, if you want to display restaurants located in Athens, Belgrade, or Berlin, your query would look like this:

$args = array(     'post_type' => 'restaurant',     'tax_query' => array(         array(             'taxonomy' => 'city',             'field'    => 'slug',             'operator' => 'IN',             'terms'    => array( 'athens', 'belgrade', 'berlin' ),         ),     ), ); $query = new WP_Query( $args ); 

Here, the 'IN' operator (used by default) ensures that posts matching any of the specified terms are returned.

Querying Multiple Taxonomies

To filter posts across multiple taxonomies, include multiple condition arrays inside tax_query. For instance, if you want to find restaurants based on both location and dish type, your query might look like this:

$args = array(     'post_type' => 'restaurant',     'tax_query' => array(         'relation' => 'AND',         array(             'taxonomy' => 'city',             'field'    => 'slug',             'terms'    => array( 'barcelona', 'kuala-lumpur' ),         ),         array(             'taxonomy' => 'dish',             'field'    => 'slug',             'terms'    => array( 'paella' ),         ),     ), ); $query = new WP_Query( $args ); 

This query will return restaurants located in either Barcelona or Kuala Lumpur that serve paella. The 'relation' => 'AND' at the top level ensures that posts must meet both conditions. Let’s take it a step further by refining queries with AND/OR logic.

Using AND and OR Logic in Queries

The 'relation' parameter allows you to define how taxonomy conditions are applied. When set to 'AND' (default), posts must meet all conditions. When set to 'OR', posts matching any of the conditions are included.

Here’s a quick comparison:

Relation Behavior Example Use Case
'AND' Posts must match all conditions Products that are both "electronics" and "on-sale"
'OR' Posts can match any condition Courses in "design" or "development" categories

For more complex filtering, you can nest relations. For example, to find products that belong to either the "laptop" or "tablet" category and are made by Apple, you can structure your query like this:

$args = array(     'post_type' => 'product',     'tax_query' => array(         'relation' => 'AND',         array(             'relation' => 'OR',             array(                 'taxonomy' => 'product-category',                 'field'    => 'slug',                 'terms'    => array( 'laptop' ),             ),             array(                 'taxonomy' => 'product-category',                 'field'    => 'slug',                 'terms'    => array( 'tablet' ),             ),         ),         array(             'taxonomy' => 'product-brand',             'field'    => 'slug',             'terms'    => array( 'apple' ),         ),     ), ); $query = new WP_Query( $args ); 

This nested structure gives you granular control over filtering logic, making it ideal for creating faceted navigation systems. Whether you’re building an eCommerce site or a content directory, this flexibility allows users to filter content by multiple attributes at the same time, ensuring a streamlined browsing experience.

Advanced Taxonomy Query Techniques

WordPress Taxonomy Query Operators and Field Types Quick Reference Guide

WordPress Taxonomy Query Operators and Field Types Quick Reference Guide

Once you’ve got the basics of taxonomy queries down, it’s time to dive into advanced techniques. These methods let you fine-tune your queries, handle tricky edge cases, and create more intricate workflows for managing content. They’re also a lifesaver when troubleshooting queries that aren’t returning the results you expect.

Using EXISTS and NOT EXISTS Operators

The EXISTS and NOT EXISTS operators are handy when you need to check whether posts are assigned any term within a specific taxonomy, without specifying the exact terms.

For example, the EXISTS operator can filter posts that have at least one term in a taxonomy. You only need to specify the taxonomy and operator – no need for terms or field. Here’s how you could display portfolio projects with at least one project type assigned:

$args = array(     'post_type' => 'portfolio',     'tax_query' => array(         array(             'taxonomy' => 'project-type',             'operator' => 'EXISTS',         ),     ), ); $query = new WP_Query( $args ); 

On the flip side, NOT EXISTS finds posts with no terms assigned to the specified taxonomy. This is especially useful for identifying uncategorized content that might need editorial attention:

$args = array(     'post_type' => 'course',     'tax_query' => array(         array(             'taxonomy' => 'course-topic',             'operator' => 'NOT EXISTS',         ),     ), ); $query = new WP_Query( $args ); 

You can even combine these operators with specific term filters. For instance, if you need to show restaurants with a city assigned but exclude those marked as "closed", you could use this approach:

$args = array(     'post_type' => 'restaurant',     'tax_query' => array(         'relation' => 'AND',         array(             'taxonomy' => 'city',             'operator' => 'EXISTS',         ),         array(             'taxonomy' => 'status',             'field'    => 'slug',             'terms'    => array( 'closed' ),             'operator' => 'NOT IN',         ),     ), ); $query = new WP_Query( $args ); 

This method is particularly useful for directory or listing platforms in the U.S., where businesses are often tied to a location taxonomy but may need filtering based on specific statuses.

Combining Taxonomy Queries with Other Parameters

By blending tax_query with other parameters like meta_query, post_status, and date_query, you can build highly tailored filters for use cases like eCommerce catalogs, event calendars, or content directories.

For example, an electronics store might want to display products in the "electronics" category that are in stock and cost $500.00 or less:

$args = array(     'post_type' => 'product',     'tax_query' => array(         array(             'taxonomy' => 'product-category',             'field'    => 'slug',             'terms'    => array( 'electronics' ),         ),     ),     'meta_query' => array(         'relation' => 'AND',         array(             'key'     => 'stock_status',             'value'   => 'in_stock',             'compare' => '=',         ),         array(             'key'     => 'price_usd',             'value'   => 500.00,             'type'    => 'NUMERIC',             'compare' => '<=',         ),     ), ); $query = new WP_Query( $args ); 

You can also mix taxonomy filters with date queries. For instance, to display only future webinars that are published, you might use this setup:

$today = date( 'Y-m-d' );  $args = array(     'post_type'      => 'event',     'post_status'    => 'publish',     'posts_per_page' => 10,     'tax_query'      => array(         array(             'taxonomy' => 'event-type',             'field'    => 'slug',             'terms'    => array( 'webinars' ),         ),     ),     'meta_query'     => array(         array(             'key'     => 'start_date',             'value'   => $today,             'type'    => 'DATE',             'compare' => '>=',         ),     ),     'orderby'        => 'meta_value',     'meta_key'       => 'start_date',     'order'          => 'ASC', ); $query = new WP_Query( $args ); 

This approach ensures that only upcoming, public events within the "webinars" taxonomy are displayed, while filtering out drafts, private posts, or past events.

Fixing Common Taxonomy Query Problems

Even with advanced queries, things can go wrong. If your taxonomy queries return zero results or unexpected posts, these common issues might be to blame. Here’s how to troubleshoot effectively:

  1. Incorrect taxonomy names: The taxonomy key in your query must match exactly what you used in register_taxonomy(). For instance, 'product-category' is not the same as 'product_category'. Double-check your registration code or plugin settings.
  2. Slug mismatches: A term’s slug often differs from its display name. For example, a category labeled "New York City" might have the slug new-york-city. You can confirm the slug by editing the term in the WordPress admin and checking its URL or slug field.
  3. Field parameter errors: If you’re using slugs, you need to explicitly set 'field' => 'slug'. If you’re using term IDs, either omit the field parameter or set it to 'term_id'. Mixing slugs and IDs in the same query can cause issues.
  4. Missing taxonomy-post type relationships: If you registered a taxonomy but didn’t assign it to your custom post type, your queries won’t return any results. Verify that the taxonomy is correctly linked to the post type.

Here’s a quick reference table for troubleshooting:

Issue Solution
Wrong taxonomy key Check the exact key in register_taxonomy()
Slug doesn’t match Verify the term’s slug in the WordPress admin
Field parameter wrong Use 'field' => 'slug' for slugs, 'term_id' for IDs
No posts returned Ensure taxonomy is assigned to the post type
Terms not showing Confirm posts have terms assigned

For debugging, tools like Query Monitor can help you see the actual SQL being generated by your query. You can also verify term assignments directly in the WordPress admin by adding taxonomy columns to the post list table. This makes it easier to spot any inconsistencies in your data or query logic.

Conclusion

Using custom post types with taxonomies in WordPress is an effective way to organize and filter content. By leveraging post_type with tax_query in WP_Query, you can create anything from simple city-filtered restaurant directories to intricate product catalogs that sort by brand, price range, and availability. The examples of Movies and Genres illustrate how flexible this approach can be. Key elements like setting the correct taxonomy, deciding between slugs and IDs with the field parameter, and using operators such as IN, NOT IN, EXISTS, and NOT EXISTS are universal. Whether you’re crafting a local business directory for a U.S. audience or a membership site with tailored content, these principles stay consistent.

These methods are scalable for high-traffic websites and work seamlessly with caching, pagination, and custom templates. By layering multiple taxonomies with AND and OR relations or combining taxonomy queries with meta queries and date filters, you can build even more complex queries. Start with a basic taxonomy query, ensure registrations are correct, and then expand your logic for more advanced use cases.

Key Takeaways

To get started, focus on these essential steps: register your custom post type, create and link taxonomies, and build a WP_Query with both post_type and tax_query parameters. Double-check that your taxonomy names match their registration, term slugs are accurate, and the field parameter corresponds to the data you’re using. If results come up empty, verify that terms are correctly assigned to posts and that your relation and operator values align with your intended logic.

Additional Learning Resources

If you’re looking to dive deeper, there are plenty of resources to refine your WordPress skills. WP Winners is a great platform offering curated tools, plugins, and step-by-step tutorials that expand on the techniques covered here. It includes practical examples of WP_Query usage, tips for optimizing complex taxonomy queries, and guides for projects like eCommerce catalogs, event calendars, and local directories tailored for U.S.-based audiences. For more detailed documentation, the official WordPress Developer Handbook is an invaluable resource, covering WP_Query, register_post_type, and register_taxonomy. Want to stay updated? Subscribe to the WP Winners newsletter for the latest best practices and techniques as WordPress continues to grow and evolve.

FAQs

How can I make sure my custom post types and taxonomies stay functional when switching WordPress themes?

When switching themes, it’s crucial to maintain the functionality of your custom post types and taxonomies. To achieve this, avoid registering them directly within your theme’s files. Instead, handle their registration through a custom plugin or a child theme. This approach ensures they remain independent of any particular theme, making transitions smoother.

Before making any changes, always back up your database to protect your content. Also, be cautious not to delete files that might contain the code for your custom post types or taxonomies. To simplify the process, you might want to use a plugin designed to create and manage these structures without relying on your theme’s code.

What are the advantages of using slugs instead of term IDs in taxonomy queries?

Using slugs in taxonomy queries can make your WordPress development process much smoother and more reliable. Unlike term IDs, which can change over time, slugs are unique, human-readable identifiers that stay consistent. This consistency ensures your code remains dependable, even if term IDs are updated or altered.

On top of that, slugs are far more intuitive when you’re working with a team or debugging issues. They clearly indicate which taxonomy term you’re referencing, making your queries easier to understand and manage. This added clarity minimizes errors and simplifies the process of maintaining or updating your WordPress site.

Why is my taxonomy query in WordPress not returning any results?

If your taxonomy query isn’t giving you any results, start by checking the taxonomy slug and term names to make sure they’re accurate. Use the tax_query parameter within WP_Query and ensure it’s configured correctly. It’s also important to confirm that the taxonomy and terms are registered properly and linked to the custom post type you’re trying to query.

Another thing to check is whether the custom post type actually supports the taxonomy. If you’re using a caching plugin, clear the cache to eliminate the possibility of outdated data interfering with your query. For troubleshooting, enable debugging by turning on WP_DEBUG in your WordPress configuration. These steps should help you pinpoint and fix most issues with taxonomy queries in WordPress.

Related Blog Posts


Discover more from WP Winners 🏆

Subscribe to get the latest posts sent to your email.

More WorDPRESS Tips, tutorials and Guides

Discover more from WP Winners 🏆

Subscribe now to keep reading and get access to the full archive.

Continue reading