Search code examples
phpwordpresscustom-post-typecustom-wordpress-pagescustom-taxonomy

How to filter archive posts based on custom taxonomy in Wordpress


I created a custom post type with a custom taxonomy. For this I used the following code in my functions.php

//Custom Posttype
function custom_post_type_rental() {
    // source: https://wordpress.stackexchange.com/questions/156978/custom-post-type-single-page-returns-404-error
        $labels = array(
            'name'               => _x( 'Rentals', 'i2sa'),
            'singular_name'      => _x( 'rentals', 'i2sa'),
            'menu_name'          => _x( 'Rentals', 'i2sa'),
            'name_admin_bar'     => _x( 'Admin Bar', 'i2sa'),
            'add_new'            => _x( 'Nieuwe rental', 'i2sa'),
            'add_new_item'       => __( 'Voeg nieuwe rental toe', 'i2sa'),
            'new_item'           => __( 'Nieuw item', 'i2sa'),
            'edit_item'          => __( 'Bewerk rentals', 'i2sa'),
            'view_item'          => __( 'Bekijk rentals', 'i2sa'),
            'all_items'          => __( 'Alle rentals', 'i2sa'),
            'search_items'       => __( 'Zoek rentals', 'i2sa'),
            'parent_item_colon'  => __( 'Parent rentals:', 'i2sa'),
            'not_found'          => __( 'Zoekopdracht niet gevonden.', 'i2sa'),
            'not_found_in_trash' => __( 'Zoekopdracht niet gevonden in prullenbak.', 'i2sa')
        );
    
        $args = array(
            'labels'             => $labels,
            'description'        => "Beschrijving i2sa",
            'public'             => true, //openbaar
            'exclude_from_search'=> true, //uitschakelen voor zoekopdrachten
            'publicly_queryable' => true, //publiekelijk vindbaar
            'show_in_nav_menus'  => false, //toon in navigatie
            'menu_icon'          => 'dashicons-bank',
            'show_ui'            => true,
            'show_in_rest'       => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => array( 'slug' => 'rental' ), //custom url
            'capability_type'    => 'post',
            'has_archive'        => true, //heeft archivepage
            'hierarchical'       => false, // true maakt het een pagina
            'menu_position'      => null, //null = geen
            'supports'           => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'author', 'trackbacks', 'comments', 'revisions', 'post-formats', 'page-attributes' ), //gesupporte functionaliteiten
            //je kan de support 'thumbnail' ook vervangen door ‘attachment:audio’ and ‘attachment:video’
        );
        register_post_type( 'rental', $args );
         //flush_rewrite_rules();
    }
add_action( 'init', 'custom_post_type_rental' );

function rentalMachineSoort() {
 
    
    //Labels voor de custom taxonomy
     $labels = array(
       'name' => _x( 'Machinesoorten', 'machinesoorten' ),
       'singular_name' => _x( 'Machinesoort', 'machinesoort' ),
       'search_items' =>  __( 'Search Machinesoorten' ),
       'all_items' => __( 'All Machinesoorten' ),
       'parent_item' => __( 'Parent Machinesoort' ),
       'parent_item_colon' => __( 'Parent Machinesoort:' ),
       'edit_item' => __( 'Edit Machinesoort' ), 
       'update_item' => __( 'Update Machinesoort' ),
       'add_new_item' => __( 'Add New Machinesoort' ),
       'new_item_name' => __( 'New Machinesoort Name' ),
       'menu_name' => __( 'Machinesoorten' ),
     );    
    
   // Taxonomy registreren
     register_taxonomy('machinesoort',array('rental'), array(
       'hierarchical' => true,
       'labels' => $labels,
       'show_ui' => true,
       'show_in_rest' => true,
       'show_admin_column' => true,
       'query_var' => true,
       'rewrite' => array( 'slug' => 'machinesoort' ),
     ));
    
   }
   add_action( 'init', 'rentalMachineSoort', 0 );

On my archive I want to filter the posts by this taxonomy. For this I used the code:

<form method="GET">
                            <select name="orderby" id="orderby">
                                <?php 
                                    $terms = get_terms([
                                        'taxonomy' => 'machinesoort',
                                        'hide_empty' => 'false'
                                    ]);
                                    foreach ($terms as $term) :
                                ?>

                                <option value="<?php echo $term->slug;?>" name="machinesoort[]"><?php echo $term->name;?></option>

                                <?php endforeach;?>
                            </select>
                            <button type="submit">Filter</button>

This makes the page refresh with a new url with a parameter included. Problem is that the page still shows all articles, including the articles that should not be shown.

Anyone knows how I can make this code work so it filters right? If I just use checkboxxes it works fine, but i need to use the methode in this filter


Solution

  • "Problem is that the page still shows all articles, including the articles that should not be shown."

    Because you're missing the main step! You have not changed the query based on the selected value!

    You could do it using pre_get_posts hook. Like this:

    add_action('pre_get_posts', 'altering_rental_archive_query', 99);
    
    function altering_rental_archive_query($query)
    {
        if (
            is_post_type_archive('rental') 
            && 
            get_query_var('orderby')
           ) 
        {
    
            $tax_query = array(
                array(
                    'taxonomy' => 'machinesoort',
                    'field' => 'slug',
                    'terms' => sanitize_text_field(get_query_var('orderby')),
                )
            );
            $query->set('tax_query', $tax_query);
        };
    };
    

    And here's the results:

    When the archive page loads for the first time without any filter(s)/query var(s):

    enter image description here


    If I filter it by the first custom taxonomy:

    enter image description here


    If I filter it by the second custom taxonomy:

    enter image description here


    One quick tip/bonus:

    You could add selectedDocs function to your form on the archive page so that your filter drop-down would get properly selected based on the queried variable up on the url:

    <form method='GET'>
      <select name='orderby' id='orderby'>
        <?php
        $terms = get_terms([
          'taxonomy' => 'machinesoort',
          'hide_empty' => 'false'
        ]);
        foreach ($terms as $term) :
        ?>
    
          <option value='<?php echo $term->slug; ?>' <?php echo selected(sanitize_text_field($_GET['orderby']), $term->slug); ?>><?php echo $term->name; ?></option>
    
        <?php endforeach; ?>
      </select>
      <button type='submit'>Filter</button>
    </form>
    

    You were also missing a closing form tag in your question! </form>.