Search code examples
phpwordpressadvanced-custom-fields

filtering posts by custom fields - url updates correctly but filtering doesn't work


I am trying to filter posts in a custom post type (gallery) by several custom fields created with ACF pro. Right now, the URL updates properly, but no matter which options are selected, no posts display on the archive-gallery page. (If I use LIKE instead of IN as the compare operator, all posts are displayed and none are filtered out).

I referred to this tutorial and code snippets and the correction shared in the single reply to this post, and to many posts on this forum raising similar questions. At one point I had this working for a single field filter, but a second field would not work. I'm not sure what I did right then, or what I'm doing wrong now. The debug log shows no errors with the following settings:

Here is the field I'm testing:

Field key: field_6174a76da315c
Field name: type_of_art
Field type: Checkbox
Choices:
visual : Visual
literary : Literary
performing : Performing
other : Other

Here is the code as it stands currently in my functions file:

// array of filters (field key => field name)
        $GLOBALS['my_query_filters'] = array( 
             'field_6174a76da315c' => 'type_of_art'
             // 'field_618edb3358d2c' => 'filter_test',

    
        );


        // action
        add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

        function my_pre_get_posts( $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['my_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 = [];
                $meta_query[] = array(
                    'key'       => $name,
                    'value'     => $value,
                    'compare'   => 'IN',
                );
                
            } 
            
            
            // update meta query
            $query->set('meta_query', $meta_query);

        }

Here's the code in my archive-gallery file:

<div id="archive-filters">
    <?php foreach( $GLOBALS['my_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; ?>
    </div>

    <script type="text/javascript">
    (function($) {
        
        // change
        $('#archive-filters').on('change', 'input[type="checkbox"]', function(){

            // vars
            var url = '<?php echo home_url('gallery'); ?>';
                args = {};
                
            
            // loop over filters
            $('#archive-filters .filter').each(function(){
                
                // vars
                var filter = $(this).data('filter'),
                    vals = [];
                
                
                // find checked inputs
                $(this).find('input:checked').each(function(){
        
                    vals.push( $(this).val() );
        
                });
                
                
                // append to args
                args[ filter ] = vals.join(',');
                
            });
            
            
            // update url
            url += '?';
            
            
            // loop over args
            $.each(args, function( name, value ){
                
                url += name + '=' + value + '&';
                
            });
            
            
            // remove last &
            url = url.slice(0, -1);
            
            
            // reload page
            window.location.replace( url );
            

        });

    })(jQuery);
    </script>

</div>

I tried adding this line of code after, to debug:

<?php echo "<pre>"; print_r($wp_query->query_vars); echo "</pre>"; ?>

And here is the result with the filter option "Visual" selected :

Array
(
    [post_type] => gallery
    [lang] => en
    [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
        (
        )

    [update_post_term_cache] => 1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => type_of_art
                    [value] => Array
                        (
                            [0] => visual
                        )

                    [compare] => IN
                )

        )

    [ignore_sticky_posts] => 
    [suppress_filters] => 
    [cache_results] => 1
    [lazy_load_term_meta] => 1
    [update_post_meta_cache] => 1
    [posts_per_page] => 10
    [nopaging] => 
    [comments_per_page] => 50
    [no_found_rows] => 
    [taxonomy] => language
    [term] => en
    [order] => DESC
)

I have confirmed that some of my test gallery posts are designated as visual for type_of_art. (The same results happen with other choices as well).

Thanks for taking a look.


Solution

  • In case anyone comes across this with similar issues — I ended up using a plugin (Search & Filter Pro) which, with some finagling, did what I needed to do.