Wordpress: Archive page with Filter doesn't wo

2020-07-11 07:12发布

问题:

Im trying to filter my custom post types by a checkbox field of ACF. I work with this tutorial: https://www.advancedcustomfields.com/resources/creating-wp-archive-custom-field-filter/

Now I got the problem that nothing change, when ich filter over the checkboxes on the archive page of the custom post type. It generates only the right URL but doesn't filter the posts.

Does some have any idea why?

function.php:

// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array( 
    'mitglieder'   => 'mitglieder'
);

// action
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 = array(
            array(
                'key'       => $name,
                'value'     => $value,
                'compare'   => 'IN',
            )
        );

    } 


    // update meta query
    $query->set('meta_query', $meta_query ); 
}
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

register_taxonomy_for_object_type('category', 'projekte'); // Register Taxonomies for Category
$labels = array(
    'name' => __('Projekte', 'projekte'), // Rename these to suit
    'singular_name' => __('Projekt', 'projekte'),
    'add_new' => __('Projekt hinzufügen', 'projekte'),
    'add_new_item' => __('Neues Projekt hinzufügen', 'projekte'),
    'edit' => __('Bearbeiten', 'projekte'),
    'edit_item' => __('Projekt bearbeiten', 'projekte'),
    'new_item' => __('Neues Projekt', 'projekte'),
    'view' => __('Anschauen', 'projekte'),
    'view_item' => __('Projekt anschauen', 'projekte'),
    'search_items' => __('Projekte durchsuchen', 'projekte'),
    'not_found' => __('Projekt wurde nicht gefunden', 'projekte'),
    'not_found_in_trash' => __('Projekt wurde nicht im Papierkorb gefunden', 'projekte')
);
$args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'query_var' => true,
    'hierarchical' => true, // Allows your posts to behave like Hierarchy Pages
    'has_archive' => true,
    'supports' => array(
        'title',
        'excerpt'
    ), // Go to Dashboard Custom HTML5 Blank post for supports
    'can_export' => true, // Allows export in Tools > Export
    'taxonomies' => array(
        'category',
    ) // Add Category and Post Tags support
);
register_post_type('projekte', $args);

archive-projekte.php:

            <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('projekte'); ?>';
                            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 );
                    });

                    $('.button.acf-add-checkbox').parent().remove();
                })(jQuery);
            </script>


            <div class="projekt-archive">
                <?php
                    $args = array(
                        'post_type' => 'projekte',
                        'post_status' => 'publish',
                        'posts_per_page' => '-1'
                    );
                    $the_query = new WP_Query( $args );

                    if ( $the_query->have_posts() ) : ?>
                        <?php while ( $the_query->have_posts() ) : ?>
                       ......
                <?php 
                    endwhile; 
                  endif;
                ?>
                <?php wp_reset_query(); ?>

回答1:

I used your code to try and recreate your issue and ran into a number of issues but got it working. On the link you supplied the video tutorial does things differently to the sample code.

The first thing I noticed is that you are changing the $query in the functions then redefining it in archive-projekte.php

$args = array(
      'post_type' => 'projekte',
      'post_status' => 'publish',
      'posts_per_page' => '-1'
);
$the_query = new WP_Query( $args );

if ( $the_query->have_posts() ) : 
   while ( $the_query->have_posts() ) : 
      //......
   endwhile; 
endif;

wp_reset_query();

you can just use a version of the standard loop instead

if ( have_posts() ) {  
   while ( have_posts() ) {
      the_post();         
      //.......
   }
}

Secondly when I set the advanced custom field(mitglieder) in Wordpress admin to be a checkbox it is then rendered as a checkbox on the front end by create_field() in the filter div but the problem is that checkboxes are saved in the meta data as serialized data so it didn't work so I changed the advanced custom field to a radio button it all works fine.

The new issue created by this is that the filter div now has radio buttons. So I watched the video tutorial and output checkboxes using a foreach loop on $field instead of using create_field, this means that the javascript needs to be changed also.

Now the only issue remains is if you need you advanced custom field to be checkbox sothat one of your projekte posts to have more than one mitglieder value then you would need to work with the serialized meta data in order to make the filter work correctly.

This works like ACF example video which uses houses and bedrooms and in that case a house cannot be a 2 bedroom house and a 3 bedroom house at the same time.