I have a custom post type product. And what I did, I made a custom filter function based on the custom post's meta data using posts_where filter. It's working but I noticed the post count is not matched on the number items displayed as seen on the image below.

enter image description here

Here's my code :

add_action( 'load-edit.php', 'load_custom_filter_wpse_94630' );

function load_custom_filter_wpse_94630()
    global $typenow;
    if( $_GET['post_type'] != 'product' )

    add_filter( 'posts_where' , 'posts_where_wpse_94630' );

function posts_where_wpse_94630( $where ) 
    global $wpdb;       
    if ( isset( $_GET[ 'location' ] ) && !empty( $_GET[ 'location' ] ) ) 
        $meta = esc_sql( $_GET['location'] );
        $where .= " AND ID IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_value='$meta' )";
    return $where;



That is normal. Even if you use the core filters, for exmaple filter by month, that numbers doesn't change. Also, you have made some mistakes in your queyr; for example, you should set the meta_key argumente in the where statement.

Anyway, I tink it is much better to use meta_query argument for the main WP_Query object. This can be done via the parse_query filter:

add_filter( 'parse_query', 'cyb_admin_posts_filter' );
function cyb_admin_posts_filter( $query ) {
    $screen = get_current_screen();
    if( is_admin() && $query->post_type == 'product' && $screen->base == 'edit.php' ) {
        if ( !empty($_GET['location']) ) {
           $query->query_vars['meta_query'] = array(
                                                  'meta_key' => 'location',
                                                  'meta_value' => esc_sql($_GET['location'])

Although I said that the post count doesn't change when using a filter as a normal behaviour, if you want ot update it you can use the views_edit-* filter (where * is the post type) and perform the query again (yes, again, a new query for each counter) to update the post counter. For example (No tested, jus writting here as example. Note that I've made it for the "All" filter, do similar task for the others filters):

add_action( 'views_edit-product', 'cyb_update_product_counter' );
function cyb_update_product_counter( $views ) {

    foreach ( $views as $index => $view ) {

         $args = array(
        'post_type'   => 'product'
         if( isset($_GET['location'] && !empty($_GET['location'] ) {
               $args['meta_query'] = array (
                                        'meta_key'    => 'location',
                                        'meta_value'  => esc_sql($_GET['location'])
         //Check for "All" filter. Do similar for other filters
         if( $index == 'all') {
             $args['all_posts'] = 1;

         //Update the count and filter links
         $query = new WP_Query($args);
         if($query->found_posts > 0) {
             $views[$index] = preg_replace( '/ <span class="count">\([0-9]+\)<\/span>/', $result->found_posts, $view );
         } else {

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.