WooCommerce指定分类页显示缺货商品,has_term失效及hook选择问题
First off, you’re spot-on about the root issue: the has_term() function doesn’t work here because when pre_get_posts runs, the global $post object hasn’t been populated for archive pages—we’re dealing with the query before any posts are fetched, so there’s no post ID to check against.
The good news is you don’t need two separate hooks—pre_get_posts is still the right tool for the job, you just need to check the current archive’s category directly from the query object instead of relying on $post.
Here’s the revised code:
add_action( 'pre_get_posts', 'VG_hide_out_of_stock_products' ); function VG_hide_out_of_stock_products( $q ) { // Skip admin and non-main queries if ( ! $q->is_main_query() || is_admin() ) { return; } // Only target product category archives if ( ! is_product_category() ) { return; } // Get the current queried category object $current_category = get_queried_object(); // Check if we're NOT on the "Sold Items" category (use slug for reliability, or name if you prefer) if ( 'sold-items' !== $current_category->slug ) { // Replace with your actual category slug if ( $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' ) ) { $tax_query = (array) $q->get('tax_query'); $tax_query[] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => array( $outofstock_term->term_taxonomy_id ), 'operator' => 'NOT IN' ); $q->set( 'tax_query', $tax_query ); } } }
Key improvements explained:
get_queried_object(): This pulls the term object for the current category archive directly from the query, which is available atpre_get_poststime (unlike the global$post).- Slug check instead of name: Using the category slug (
sold-items) is more reliable than the name, since slugs don’t change if you edit the category’s display name later. If you must use the name, replace the condition with'Sold Items' !== $current_category->name. - Target only product category archives: We add
is_product_category()to make sure we’re only modifying queries on product category pages, avoiding unintended changes to other archives or single product pages.
Why you don’t need two hooks:
All the logic can live in pre_get_posts because we’re checking the query’s context directly. There’s no need to split into separate hooks—this approach keeps your code clean and efficient.
内容的提问来源于stack exchange,提问作者daveidivide

