Support

Account

Home Forums ACF PRO Filters on custom taxonomy page

Solved

Filters on custom taxonomy page

  • Hi,

    I have a page (rendered using the taxonomy-{slug}.php template, based on archive.php) that displays all posts allocated to a term within that taxonomy. I would like to add a filter to it based on a custom checkbox field. I have followed the instructions in the documentation; the checkboxes display on the frontend, the URL updates accordingly when checking a checkbox but the query does not update and filter the posts. After some debugging I’ve noticed that !$query->is_main_query() always returns true, thus not proceeding with the rest of the function. How can I get this to work on this custom taxonomy page? I also had the same result on a custom post type archive (archive-{post_type}.php) despite copying the exact same code from the documentation, only changing the field key (field name) and field name (field label).

    Thanks in advance 🙂

  • (my reply got deleted somehow after editing so I’m reposting…)

    I did some more debugging and noticed that meta_query is getting populated (inside query_vars) but it still doesn’t filter the posts. The loop remains unaffected and all posts are being displayed on both the taxonomy page and custom post type archive instead of getting filtered by the custom field pb_region => region.

    Here’s what $query outputs currently on the taxonomy page after setting meta_query:

    WP_Query Object
    (
        [query] => Array
            (
                [games] => totk
            )
    
        [query_vars] => Array
            (
                [games] => totk
                [error] => 
                [m] => 
                [p] => 0
                [post_parent] => 
                [subpost] => 
                [subpost_id] => 
                [attachment] => 
                [attachment_id] => 0
                [name] => 
                [pagename] => 
                [page_id] => 0
                [second] => 
                [minute] => 
                [hour] => 
                [day] => 0
                [monthnum] => 0
                [year] => 0
                [w] => 0
                [category_name] => 
                [tag] => 
                [cat] => 
                [tag_id] => 
                [author] => 
                [author_name] => 
                [feed] => 
                [tb] => 
                [paged] => 0
                [meta_key] => 
                [meta_value] => 
                [preview] => 
                [s] => 
                [sentence] => 
                [title] => 
                [fields] => 
                [menu_order] => 
                [embed] => 
                [category__in] => Array
                    (
                    )
    
                [category__not_in] => Array
                    (
                    )
    
                [category__and] => Array
                    (
                    )
    
                [post__in] => Array
                    (
                    )
    
                [post__not_in] => Array
                    (
                    )
    
                [post_name__in] => Array
                    (
                    )
    
                [tag__in] => Array
                    (
                    )
    
                [tag__not_in] => Array
                    (
                    )
    
                [tag__and] => Array
                    (
                    )
    
                [tag_slug__in] => Array
                    (
                    )
    
                [tag_slug__and] => Array
                    (
                    )
    
                [post_parent__in] => Array
                    (
                    )
    
                [post_parent__not_in] => Array
                    (
                    )
    
                [author__in] => Array
                    (
                    )
    
                [author__not_in] => Array
                    (
                    )
    
                [search_columns] => Array
                    (
                    )
    
                [meta_query] => Array
                    (
                        [key] => region
                        [value] => Array
                            (
                                [0] => eu
                                [1] => na
                            )
    
                        [compare] => IN
                    )
    
            )
    
        [tax_query] => WP_Tax_Query Object
            (
                [queries] => Array
                    (
                        [0] => Array
                            (
                                [taxonomy] => games
                                [terms] => Array
                                    (
                                        [0] => totk
                                    )
    
                                [field] => slug
                                [operator] => IN
                                [include_children] => 1
                            )
    
                    )
    
                [relation] => AND
                [table_aliases:protected] => Array
                    (
                    )
    
                [queried_terms] => Array
                    (
                        [games] => Array
                            (
                                [terms] => Array
                                    (
                                        [0] => totk
                                    )
    
                                [field] => slug
                            )
    
                    )
    
                [primary_table] => 
                [primary_id_column] => 
            )
    
        [meta_query] => 
        [date_query] => 
        [post_count] => 0
        [current_post] => -1
        [in_the_loop] => 
        [comment_count] => 0
        [current_comment] => -1
        [found_posts] => 0
        [max_num_pages] => 0
        [max_num_comment_pages] => 0
        [is_single] => 
        [is_preview] => 
        [is_page] => 
        [is_archive] => 1
        [is_date] => 
        [is_year] => 
        [is_month] => 
        [is_day] => 
        [is_time] => 
        [is_author] => 
        [is_category] => 
        [is_tag] => 
        [is_tax] => 1
        [is_search] => 
        [is_feed] => 
        [is_comment_feed] => 
        [is_trackback] => 
        [is_home] => 
        [is_privacy_policy] => 
        [is_404] => 
        [is_embed] => 
        [is_paged] => 
        [is_admin] => 
        [is_attachment] => 
        [is_singular] => 
        [is_robots] => 
        [is_favicon] => 
        [is_posts_page] => 
        [is_post_type_archive] => 
        [...]
    )

    And this is the template (just excluding the header and footer):

    <?php $term = get_queried_object();  ?>
    
    <?php if ( have_posts() ) : ?>
      <div class="container">
        <div id="primary" class="content products">
          <div class="filters">
            <?php foreach( $GLOBALS['query_filters'] as $key => $name ): 
                
              // get the field's settings without attempting to load a value
              $field = get_field_object($key, false, false); 
    
              // set value if available
              if( isset($_GET[ $name ]) ) {
                  
                $field['value'] = explode(',', $_GET[ $name ]);
                  
              }
              
              // create filter
              ?>
              <div class="filter" data-filter="<?php echo $name; ?>">
                <?php create_field( $field ); ?>
              </div>
                
            <?php endforeach; ?>
            <input type="hidden" class="js-filter-url" value="<?php echo home_url('products/' . $term->slug . '/'); ?>" />
          </div>
        </div>
    
        <div class="product-grid">
            <?php
    
            while ( have_posts() ) : the_post();
    
                get_template_part( 'template-parts/post/content', 'product' );
    
            endwhile; ?>
            </div>
        </div>
    
    <?php else : ?>
    
    	<div class="container-s">
    		<div id="primary" class="content">
    			<?php get_template_part( 'template-parts/post/content', 'none' ); ?>
    		</div>
    	</div>
    
    <?php endif; ?>

    This is what $query outputs on the custom post type archive:

    WP_Query Object
    (
        [query] => Array
            (
                [post_type] => products
            )
    
        [query_vars] => Array
            (
                [post_type] => products
                [error] => 
                [m] => 
                [p] => 0
                [post_parent] => 
                [subpost] => 
                [subpost_id] => 
                [attachment] => 
                [attachment_id] => 0
                [name] => 
                [pagename] => 
                [page_id] => 0
                [second] => 
                [minute] => 
                [hour] => 
                [day] => 0
                [monthnum] => 0
                [year] => 0
                [w] => 0
                [category_name] => 
                [tag] => 
                [cat] => 
                [tag_id] => 
                [author] => 
                [author_name] => 
                [feed] => 
                [tb] => 
                [paged] => 0
                [meta_key] => 
                [meta_value] => 
                [preview] => 
                [s] => 
                [sentence] => 
                [title] => 
                [fields] => 
                [menu_order] => 
                [embed] => 
                [category__in] => Array
                    (
                    )
    
                [category__not_in] => Array
                    (
                    )
    
                [category__and] => Array
                    (
                    )
    
                [post__in] => Array
                    (
                    )
    
                [post__not_in] => Array
                    (
                    )
    
                [post_name__in] => Array
                    (
                    )
    
                [tag__in] => Array
                    (
                    )
    
                [tag__not_in] => Array
                    (
                    )
    
                [tag__and] => Array
                    (
                    )
    
                [tag_slug__in] => Array
                    (
                    )
    
                [tag_slug__and] => Array
                    (
                    )
    
                [post_parent__in] => Array
                    (
                    )
    
                [post_parent__not_in] => Array
                    (
                    )
    
                [author__in] => Array
                    (
                    )
    
                [author__not_in] => Array
                    (
                    )
    
                [search_columns] => Array
                    (
                    )
    
                [meta_query] => Array
                    (
                        [key] => region
                        [value] => Array
                            (
                                [0] => as
                            )
    
                        [compare] => IN
                    )
    
            )
    
        [tax_query] => WP_Tax_Query Object
            (
                [queries] => Array
                    (
                    )
    
                [relation] => AND
                [table_aliases:protected] => Array
                    (
                    )
    
                [queried_terms] => Array
                    (
                    )
    
                [primary_table] => 
                [primary_id_column] => 
            )
    
        [meta_query] => 
        [date_query] => 
        [post_count] => 0
        [current_post] => -1
        [in_the_loop] => 
        [comment_count] => 0
        [current_comment] => -1
        [found_posts] => 0
        [max_num_pages] => 0
        [max_num_comment_pages] => 0
        [is_single] => 
        [is_preview] => 
        [is_page] => 
        [is_archive] => 1
        [is_date] => 
        [is_year] => 
        [is_month] => 
        [is_day] => 
        [is_time] => 
        [is_author] => 
        [is_category] => 
        [is_tag] => 
        [is_tax] => 
        [is_search] => 
        [is_feed] => 
        [is_comment_feed] => 
        [is_trackback] => 
        [is_home] => 
        [is_privacy_policy] => 
        [is_404] => 
        [is_embed] => 
        [is_paged] => 
        [is_admin] => 
        [is_attachment] => 
        [is_singular] => 
        [is_robots] => 
        [is_favicon] => 
        [is_posts_page] => 
        [is_post_type_archive] => 1
        [...]
    )

    And the template:

    <?php if ( have_posts() ) : ?>
      <div class="container">
        <div class="filters">
          <?php foreach( $GLOBALS['query_filters'] as $key => $name ): 
              
            // get the field's settings without attempting to load a value
            $field = get_field_object($key, false, false); 
    
            // set value if available
            if( isset($_GET[ $name ]) ) {
                
              $field['value'] = explode(',', $_GET[ $name ]);
                
            }
            
            // create filter
            ?>
            <div class="filter" data-filter="<?php echo $name; ?>">
              <?php create_field( $field ); ?>
            </div>
              
          <?php endforeach; ?>
          <input type="hidden" class="js-filter-url" value="<?php echo home_url('products'); ?>" />
        </div>
    
        <div class="product-grid">
          <?php
          /* Start the Loop */
          while ( have_posts() ) : the_post();
            get_template_part( 'template-parts/post/content', 'product' );
          endwhile; ?>
        </div>
      </div>
    
    <?php else : ?>
    
      <div class="container-s">
        <div id="primary" class="content">
          <?php get_template_part( 'template-parts/post/content', 'none' ); ?>
        </div>
      </div>
    
    <?php endif; ?>

    This is in my functions.php:

    $GLOBALS['query_filters'] = array( 
        'pb_region'   => 'region'
    );
    
    // action
    add_action('pre_get_posts', 'tmr_filter', 10, 1);
    function tmr_filter( $query ) {
        // bail early if is in admin
        if( is_admin() ) return;
    
        // bail early if not main query
        // - allows custom code / plugins to continue working
        if( !$query->is_main_query() ) return;
    
        // get meta query
        $meta_query = $query->get('meta_query');
        
        // loop over filters
        foreach( $GLOBALS['query_filters'] as $key => $name ) {
            
            // continue if not found in url
            if( empty($_GET[ $name ]) ) {
                continue;
            }
    			
            // get the value for this filter
            // eg: http://www.website.com/events?city=melbourne,sydney
            $value = explode(',', $_GET[ $name ]);
    			
            //append meta query
            $meta_query = array(
                'key'       => $name,
                'value'     => $value,
                'compare'   => 'IN'
            );
        } 
        
        // update meta query
       $query->set('meta_query', $meta_query);
    }

    Any pointers? Many thanks in advance!

  • Another update… Turns out that the database can’t find any posts using the code examples from the documentation and it’s not possible to use the IN operator for checkboxes. I could only find results with the following SQL:

    SELECT * FROM cms_posts INNER JOIN cms_postmeta ON( cms_posts.ID = cms_postmeta.post_id ) WHERE 1 = 1 AND( ( cms_postmeta.meta_key = 'pb_region' AND cms_postmeta.meta_value LIKE '%eu%' ) ) GROUP BY cms_posts.ID ORDER BY cms_posts.post_title ASC;

    And the posts get filtered only if I set custom arguments in the template itself and manually setting the meta_query but not when using pre_get_posts(I already checked if there was another instance overriding it, there isn’t).

    This is the query when looping through a custom query and meta_query defined with a string value:

    WP_Query Object
    (
        [query] => Array
            (
                [post_type] => products
                [orderby] => title
                [order] => ASC
                [posts_per_page] => -1
                [tax_query] => Array
                    (
                        [taxonomy] => games
                        [term] => totk
                    )
    
                [meta_query] => Array
                    (
                        [0] => Array
                            (
                                [key] => pb_region
                                [value] => eu
                                [compare] => LIKE
                            )
    
                    )
    
            )
    
        [query_vars] => Array
            (
                [post_type] => products
                [orderby] => title
                [order] => ASC
                [posts_per_page] => -1
                [tax_query] => Array
                    (
                        [taxonomy] => games
                        [term] => totk
                    )
    
                [meta_query] => Array
                    (
                        [0] => Array
                            (
                                [key] => pb_region
                                [value] => eu
                                [compare] => LIKE
                            )
    
                    )
                [...]
            )
    
        [...]
        [meta_query] => WP_Meta_Query Object
            (
                [queries] => Array
                    (
                        [0] => Array
                            (
                                [key] => pb_region
                                [value] => eu
                                [compare] => LIKE
                            )
    
                        [relation] => OR
                    )
    
                [relation] => AND
                [meta_table] => cms_postmeta
                [meta_id_column] => post_id
                [primary_table] => cms_posts
                [primary_id_column] => ID
                [table_aliases:protected] => Array
                    (
                        [0] => cms_postmeta
                    )
    
                [clauses:protected] => Array
                    (
                        [cms_postmeta] => Array
                            (
                                [key] => pb_region
                                [value] => eu
                                [compare] => LIKE
                                [compare_key] => =
                                [alias] => cms_postmeta
                                [cast] => CHAR
                            )
    
                    )
    
                [has_or_relation:protected] => 
            )
        [...]
    

    This is my current code, by the way:

    $meta_query = array(
    	'key'       => $name,
    	'value'     => $value,
    	'compare'   => 'LIKE'
    );

    Any input would be much appreciated.

  • Ended up replacing the custom checkbox field with another custom taxonomy.

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.