You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress自定义文章类型分类分页查询:如何按分类筛选文章?

Filter WordPress Posts by Category in Custom WPDB Pagination Query

Got it, let's work through this. Your current query pulls all published "articles" post type entries, but to filter by category, we need to account for how WordPress stores taxonomy data—categories aren't stored directly in the posts table, so we'll need to join the taxonomy-related tables. Here's how to adjust your code properly:

Step 1: Sanitize the Category Input

First, we need to safely receive and clean the category parameter (whether you're using a category ID or slug). Let's use ID as the example, but I'll include the slug variant too:

// Sanitize category ID (use this if you're passing category ID via POST)
$category_id = isset($_POST['category_id']) ? absint($_POST['category_id']) : 0;

// OR if you're using category slug instead:
// $category_slug = isset($_POST['category_slug']) ? sanitize_text_field($_POST['category_slug']) : '';

Step 2: Adjust the Query with Taxonomy Joins

WordPress links posts to categories using three tables:

  • wp_term_relationships: Connects posts to taxonomy entries
  • wp_term_taxonomy: Defines the type of taxonomy (e.g., "category")
  • wp_terms: Stores the category name/slug/ID

We'll join these tables to your existing query, add a conditional filter for the category, and fix the offset calculation (your original offset would skip the first page's posts if page=1):

$per_page = 8;
// Ensure page is a valid positive integer, default to 1 if not set
$page = isset($_POST['page']) ? absint($_POST['page']) : 1;
// Fix offset: page 1 should start at 0, not 8
$start = ($page - 1) * $per_page;

// Base query with joins to taxonomy tables
$query = "
    SELECT p.*
    FROM {$wpdb->posts} p
    LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
    LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
    LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
    WHERE p.post_type = 'articles' 
      AND p.post_status = 'publish'
";

// Add category filter only if a valid category ID is provided
if ($category_id > 0) {
    $query .= " AND tt.taxonomy = 'category' AND tt.term_id = %d";
}

// OR if using category slug:
// if (!empty($category_slug)) {
//     $query .= " AND tt.taxonomy = 'category' AND t.slug = %s";
// }

// Add grouping (to avoid duplicate posts if a post is in multiple categories), order, and limit
$query .= " GROUP BY p.ID ORDER BY p.post_date DESC LIMIT %d, %d";

// Prepare parameters for the query
$params = [];
if ($category_id > 0) {
    $params[] = $category_id;
}
// Uncomment if using slug:
// if (!empty($category_slug)) {
//     $params[] = $category_slug;
// }
$params[] = $start;
$params[] = $per_page;

// Execute the prepared query (critical for preventing SQL injection)
$posts = $wpdb->get_results($wpdb->prepare($query, $params));

Key Notes:

  • Offset Fix: ($page - 1) * $per_page ensures page 1 starts at the first post (offset 0) instead of skipping the first 8.
  • Group by Post ID: This prevents duplicate post results if an article is assigned to multiple categories.
  • SQL Injection Protection: We use absint(), sanitize_text_field(), and $wpdb->prepare() to keep the query safe.

If you don't strictly need a custom WPDB query, WordPress's built-in WP_Query is more maintainable—it handles taxonomy filters, pagination, caching, and edge cases automatically:

$args = [
    'post_type' => 'articles',
    'post_status' => 'publish',
    'posts_per_page' => $per_page,
    'paged' => $page,
    'orderby' => 'date',
    'order' => 'DESC',
];

// Add category filter
if ($category_id > 0) {
    $args['cat'] = $category_id;
    // OR for slug:
    // $args['category_name'] = $category_slug;
}

$wp_query = new WP_Query($args);
$posts = $wp_query->posts;

This approach is less error-prone and leverages WordPress's core functionality, so it's the better choice for most cases.

内容的提问来源于stack exchange,提问作者Sudhakar SJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:08:38