Filtering posts by custom fields and taxonomies
Besides using Tag and Category to filter your posts, you can also use custom fields and custom taxonomies to do it. This is a tutorial on doing it with the example of creating two filters for a bookselling site with two different features: publishers and authors.
Video Version
Here are some tools we need:
- Meta Box to have a framework to create custom post types and custom fields. It’s free and available on wordpress.org;
- MB Custom Post Type & Custom Taxonomies: to create a custom post type named Book and a custom taxonomy named Publishers;
- Meta Box Builder: to have an intuitive UI to create custom fields for Book custom post type in the backend.
Using custom taxonomies
1. Creating a custom taxonomy
Since I’ve already had a custom post type named Books, I will create a custom taxonomy for it. If you don't know how to create a custom post type, refer to this article for more details.
Go to Meta Box > Taxonomies > Add New to create the taxonomies. Then, just fill in the information for it.
To assign this taxonomy to the Book post type, move to the Post Types tab and tick to the Book option.
If you want to display the list of the taxonomy’s terms as a checkbox list in the post editor like the below pic, just go to Advanced tab, tick the Hierarchical box.
Otherwise, if you do not check the Hierarchical box, the taxonomy section will display like this:
After publishing the taxonomy, you will see it in the Book menu.
Now, you can create terms for the taxonomy.
Then, you will see all the terms displayed in the post editor.
2. Displaying the taxonomy terms on the archive page
Go to Appearance > Theme File Editor > archive.php
and add this code to where you want to show the terms on the archive page.
<div class="filter-custom-taxonomy">
<?php $terms = get_terms( 'publisher' ) ?>
<?php foreach ( $terms as $term ) : ?>
<a href="?getby=cat&cat=<?= esc_attr( $term->slug ) ?>">
<?= esc_html( $term->name ) ?>
</a>
<?php endforeach; ?>
</div>
In there, publisher is the slug of the created taxonomy. You can replace it with your own one.
This is how your term displays in the archive page:
3. Getting posts by the taxonomy terms
Still in the Theme File Editor, go to the functions.php
file, add these codes:
function yourprefix_filter_archive_by_tax( $query ) {
if ( is_admin() || ! $query->is_archive() || ! $query->is_main_query() || empty( $_GET['getby'] ) || 'cat' !== $_GET['getby'] ) {
return;
}
$tax_query = [
[
'taxonomy' => 'publisher',
'field' => 'slug',
'terms' => $_GET['cat'],
],
];
$query->set( 'tax_query', $tax_query );
return $query;
}
add_action( 'pre_get_posts', ‘yourprefix_filter_archive_by_tax’);
In this code:
yourprefix_filter_archive_by_tax
: This is the name that I set for the function. You can name it as you wantif ( is_admin() || ! $query->is_archive() || ! $query->is_main_query() || empty( $_GET['getby'] ) || 'cat' !== $_GET['getby'] ) {
: This statement does check if the user is on the archive page on frontend and it runs the main query or not.$tax_query = [ ['taxonomy' => 'publisher', 'field' => 'slug', 'terms' => $_GET['cat'], ], ];
: This is to declare the variable to get the posts which have the taxonomy’s slug aspublisher
.terms
=> $_GET['cat']
is used to get the slug of the terms inside the taxonomy.add_action( 'pre_get_posts', ‘yourprefix_filter_archive_by_tax’);
: This is used to add a callback function to an action hook.pre_get_posts
is the name of the hook filter and theyourprefix_filter_archive_by_tax
is a callback to add intopre_get_posts
. We usepre_get_posts
to modify the query to get the wanted posts. We simply add atax_query
by publisher to get posts that have the selected term.
Here is the final result. All books of that term are filtered.
Using custom fields
1. Creating a custom field
First of all, create a custom field named Author for the Book post type. This data saved in the custom field will be used for the filter.
In the Admin Dashboard, go to Meta Box > Custom Fields > Add New > Add Fields. For the Book’s Author, I set it as a Text field to easily fill in the name of the author.
Note that, you should remember the field’s ID to add it to the code.
Move to the Settings tab, choose Location as Post Type, and select Book to apply this field to this post type.
Here is the created custom field in the post editor.
2. Displaying the list of fields’ value
Add these codes below in the archive.php file
to show the custom field’s values:
<div class="filter-custom-field">
<?php
global $wpdb;
$meta_values = $wpdb->get_col( "SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key='book_author'" );
foreach ( $meta_values as $meta_value ) : ?>
<a href="?getby=field&field=<?= esc_attr( $meta_value ) ?>">
<?= esc_html( $meta_value ) ?>
</a>
<?php endforeach ?>
</div>
In this code, we use a raw SQL query to get all values of the book_author
custom field. These values are stored in the post meta table.
Now, in the archive page, all the created custom fields have been obtained.
3. Getting posts by custom field’s values
In the functions.php
file, use these codes to set the filter action:
function yourprefix_filter_archive_by_field( $query ) {
if ( is_admin() || ! $query->is_archive() || ! $query->is_main_query() || empty( $_GET['getby'] ) || 'field' !== $_GET['getby'] ) {
return;
}
$query->set( 'meta_key', 'book_author' );
$query->set( 'meta_value', $_GET['field'] );
return $query;
}
add_action( 'pre_get_posts',’yourprefix_filter_archive_by_field’);
Similar to filter posts by taxonomy, we use the pre_get_action
and set the query parameters for meta query: meta_key
, meta_value
.
Here is the result when I filter all books of the author: