This is How to Get WordPress Posts By Category But Exclude Subcategories
As a WordPress developer, one of the most common tasks you'll encounter is displaying posts by category on your website. However, things can get tricky when you need to exclude subcategories from the mix.
There's no built-in WordPress function that allows you to easily achieve this. The closest solution would be the get_posts()
function, but even that has some limitations when it comes to excluding subcategories.
In this comprehensive guide, we'll dive deep into the problem and walk you through step-by-step solutions to get WordPress posts by category while excluding subcategories. Whether you're a seasoned developer or just starting out, you'll find the information here useful for improving your website's content organization and navigation.
Understanding the Challenge
The core issue lies in the way WordPress handles categories and subcategories. When you use the standard get_posts()
function to retrieve posts by category, it will also include posts from any subcategories associated with that main category.
For example, let's say you have a main category called "News" and two subcategories: "Company News" and "Industry News." If you use get_posts()
to fetch posts from the "News" category, you'll end up getting posts from all three categories – the main "News" category, as well as the two subcategories.
This behavior might not always be desirable, especially if you want to display posts from the main category only, without the subcategories. Imagine having a dedicated "News" page that should show only the posts from the main "News" category, not the subcategories.
The Solution: Custom SQL Query
Since there's no built-in WordPress function to achieve this, we'll need to resort to a custom SQL query to get the job done. Here's the step-by-step process:
-
Determine the Category ID: First, you'll need to find the ID of the main category you want to display posts for. You can do this by navigating to the "Categories" section in your WordPress admin dashboard, then clicking on the category you want to work with. The category ID will be visible in the URL.
-
Exclude Subcategory IDs: Next, you'll need to find the IDs of any subcategories associated with the main category. You can do this by querying the wp_terms
and wp_term_taxonomy
tables in your WordPress database.
SELECT term_id
FROM wp_terms
WHERE term_id IN (
SELECT term_id
FROM wp_term_taxonomy
WHERE parent = [MAIN_CATEGORY_ID]
);
Replace [MAIN_CATEGORY_ID]
with the ID of the main category you identified in step 1.
-
Build the Custom Query: Now that you have the ID of the main category and the IDs of any subcategories, you can construct the custom SQL query to retrieve the posts. Here's an example:
SELECT p.*
FROM wp_posts p
INNER JOIN wp_term_relationships tr ON p.ID = tr.object_id
WHERE tr.term_taxonomy_id = [MAIN_CATEGORY_ID]
AND p.post_type = 'post'
AND p.post_status = 'publish'
AND tr.term_taxonomy_id NOT IN ([SUBCATEGORY_IDS])
ORDER BY p.post_date DESC
Replace [MAIN_CATEGORY_ID]
with the ID of the main category, and [SUBCATEGORY_IDS]
with the IDs of the subcategories, separated by commas (e.g., 12, 34, 56
).
This query will retrieve all published posts that belong to the main category, while excluding any posts that are associated with the subcategories.
-
Integrate the Query into WordPress: To use this custom query in your WordPress theme or plugin, you can wrap it in the $wpdb->get_results()
function, like this:
global $wpdb;
$main_category_id = 123; // Replace with your main category ID
$subcategory_ids = array(456, 789); // Replace with your subcategory IDs
$query = $wpdb->prepare(
"SELECT p.*
FROM wp_posts p
INNER JOIN wp_term_relationships tr ON p.ID = tr.object_id
WHERE tr.term_taxonomy_id = %d
AND p.post_type = 'post'
AND p.post_status = 'publish'
AND tr.term_taxonomy_id NOT IN (" . implode(',', array_fill(0, count($subcategory_ids), '%d')) . ")
ORDER BY p.post_date DESC",
array_merge(array($main_category_id), $subcategory_ids)
);
$posts = $wpdb->get_results($query);
This example uses the $wpdb->prepare()
function to safely interpolate the category and subcategory IDs into the SQL query, preventing SQL injection attacks.
Once you have the $posts
array, you can use it to display the filtered posts on your website, just like you would with the standard get_posts()
function.
Real-World Example
Let's say you have a WordPress website with a "News" category and two subcategories: "Company News" and "Industry News." You want to create a dedicated "News" page that displays posts from the main "News" category only, without the subcategories.
Using the steps outlined above, here's how you can achieve this:
-
Determine the ID of the "News" category, which let's assume is 123
.
-
Find the IDs of the "Company News" and "Industry News" subcategories, which let's assume are 456
and 789
respectively.
-
Construct the custom SQL query:
SELECT p.*
FROM wp_posts p
INNER JOIN wp_term_relationships tr ON p.ID = tr.object_id
WHERE tr.term_taxonomy_id = 123
AND p.post_type = 'post'
AND p.post_status = 'publish'
AND tr.term_taxonomy_id NOT IN (456, 789)
ORDER BY p.post_date DESC
-
Integrate the query into your WordPress theme or plugin:
global $wpdb;
$main_category_id = 123;
$subcategory_ids = array(456, 789);
$query = $wpdb->prepare(
"SELECT p.*
FROM wp_posts p
INNER JOIN wp_term_relationships tr ON p.ID = tr.object_id
WHERE tr.term_taxonomy_id = %d
AND p.post_type = 'post'
AND p.post_status = 'publish'
AND tr.term_taxonomy_id NOT IN (" . implode(',', array_fill(0, count($subcategory_ids), '%d')) . ")
ORDER BY p.post_date DESC",
array_merge(array($main_category_id), $subcategory_ids)
);
$posts = $wpdb->get_results($query);
// Use the $posts array to display the filtered news posts
Now, when you display the "News" page on your website, it will only show posts from the main "News" category, excluding any posts from the "Company News" and "Industry News" subcategories.
Conclusion
Excluding subcategories when retrieving WordPress posts by category is a common challenge, but with the right approach, you can easily overcome it. By using a custom SQL query, you can precisely filter the posts to display only the content you want, improving the organization and navigation of your website.
Remember, the key steps are:
- Determine the ID of the main category you want to display posts for.
- Find the IDs of any subcategories associated with the main category.
- Construct the custom SQL query to retrieve the posts, excluding the subcategory posts.
- Integrate the query into your WordPress theme or plugin.
With this knowledge, you can now tackle similar challenges and create more sophisticated content management systems for your WordPress websites. If you need further assistance or want to explore how Flowpoint.ai can help you identify and fix technical issues on your website, don't hesitate to reach out.
Get a Free AI Website Audit
Automatically identify UX and content issues affecting your conversion rates with Flowpoint's comprehensive AI-driven website audit.