Let users sort posts in Wordpress
Categories:
Empowering Users: Implementing Custom Post Sorting in WordPress

Learn how to give your WordPress users control over how posts are displayed, enhancing user experience with custom sorting options for various content types.
WordPress, by default, offers limited sorting options for posts and custom post types. While administrators can reorder content in the backend, providing front-end sorting capabilities directly to users significantly improves site usability and engagement. This article will guide you through implementing custom sorting mechanisms, allowing your users to dynamically reorder posts based on criteria like title, date, or custom fields.
Understanding WordPress Query and Sorting
At the heart of WordPress content display is the WP_Query
class. This powerful class is responsible for fetching posts from the database based on a wide array of parameters, including sorting. When you visit an archive page, a search results page, or even the main blog page, WP_Query
is working behind the scenes to retrieve and order the content. To implement custom sorting, we need to modify the query parameters before WP_Query
executes.
flowchart TD A[User Visits Page] --> B{WordPress Initializes} B --> C[Pre_get_posts Action Hook] C --> D{Check for Sorting Parameters?} D -- Yes --> E[Modify WP_Query 'orderby' & 'order'] D -- No --> F[Use Default Sorting] E --> G[WP_Query Executes] F --> G G --> H[Display Sorted Posts]
WordPress Query Flow with Custom Sorting Integration
The pre_get_posts
action hook is our primary tool for intercepting and modifying the main query. This hook fires before the query is executed, allowing us to inject our custom sorting logic. We'll combine this with URL parameters to let users select their preferred sorting method.
Implementing Basic Sorting Options
Let's start by adding a simple dropdown menu to your archive pages that allows users to sort posts by title or date. We'll use URL parameters to pass the sorting preference to our pre_get_posts
function.
<?php
// functions.php or a custom plugin file
function my_custom_sort_posts( $query ) {
// Ensure we are on the front-end, not in the admin, and it's the main query
if ( ! is_admin() && $query->is_main_query() ) {
// Check if a sort parameter is present in the URL
if ( isset( $_GET['sort_by'] ) ) {
$sort_by = sanitize_text_field( $_GET['sort_by'] );
switch ( $sort_by ) {
case 'title_asc':
$query->set( 'orderby', 'title' );
$query->set( 'order', 'ASC' );
break;
case 'title_desc':
$query->set( 'orderby', 'title' );
$query->set( 'order', 'DESC' );
break;
case 'date_asc':
$query->set( 'orderby', 'date' );
$query->set( 'order', 'ASC' );
break;
case 'date_desc':
$query->set( 'orderby', 'date' );
$query->set( 'order', 'DESC' );
break;
// Add more cases for other sorting options
default:
// Fallback to default WordPress sorting if parameter is invalid
break;
}
}
}
}
add_action( 'pre_get_posts', 'my_custom_sort_posts' );
// Function to display the sorting dropdown in your theme template
function display_sort_dropdown() {
$current_sort = isset( $_GET['sort_by'] ) ? sanitize_text_field( $_GET['sort_by'] ) : '';
$current_url = remove_query_arg( 'sort_by', get_permalink() ); // Get current URL without existing sort_by param
?>
<form action="<?php echo esc_url( $current_url ); ?>" method="get">
<label for="sort_by">Sort by:</label>
<select name="sort_by" id="sort_by" onchange="this.form.submit()">
<option value="date_desc" <?php selected( $current_sort, 'date_desc' ); ?>>Date (Newest First)</option>
<option value="date_asc" <?php selected( $current_sort, 'date_asc' ); ?>>Date (Oldest First)</option>
<option value="title_asc" <?php selected( $current_sort, 'title_asc' ); ?>>Title (A-Z)</option>
<option value="title_desc" <?php selected( $current_sort, 'title_desc' ); ?>>Title (Z-A)</option>
</select>
<?php
// Preserve other query parameters if they exist (e.g., category, search)
foreach ( $_GET as $key => $value ) {
if ( $key !== 'sort_by' ) {
echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '">';
}
}
?>
</form>
<?php
}
// Example of where to call the dropdown in your theme (e.g., archive.php, category.php)
// <?php display_sort_dropdown(); ?>
sanitize_text_field()
for user-provided input from $_GET
or $_POST
to prevent XSS vulnerabilities. Also, use esc_url()
and esc_attr()
when outputting URLs and attributes.Sorting by Custom Fields (Meta Keys)
Many WordPress sites utilize custom fields (post meta) to store additional data. You can also sort posts based on these custom fields. This requires a slightly different approach within pre_get_posts
.
<?php
// Extend the previous my_custom_sort_posts function
function my_custom_sort_posts_with_meta( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
if ( isset( $_GET['sort_by'] ) ) {
$sort_by = sanitize_text_field( $_GET['sort_by'] );
switch ( $sort_by ) {
// ... (previous cases for title, date) ...
case 'price_asc':
$query->set( 'orderby', 'meta_value_num' ); // Use meta_value_num for numeric sorting
$query->set( 'meta_key', 'product_price' ); // The custom field key
$query->set( 'order', 'ASC' );
break;
case 'price_desc':
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'product_price' );
$query->set( 'order', 'DESC' );
break;
case 'rating_desc':
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'average_rating' );
$query->set( 'order', 'DESC' );
break;
case 'rating_asc':
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'average_rating' );
$query->set( 'order', 'ASC' );
break;
// Add more cases for other custom fields
default:
break;
}
}
}
}
add_action( 'pre_get_posts', 'my_custom_sort_posts_with_meta' );
// Update the display_sort_dropdown function to include new options
function display_sort_dropdown_with_meta() {
$current_sort = isset( $_GET['sort_by'] ) ? sanitize_text_field( $_GET['sort_by'] ) : '';
$current_url = remove_query_arg( 'sort_by', get_permalink() );
?>
<form action="<?php echo esc_url( $current_url ); ?>" method="get">
<label for="sort_by">Sort by:</label>
<select name="sort_by" id="sort_by" onchange="this.form.submit()">
<option value="date_desc" <?php selected( $current_sort, 'date_desc' ); ?>>Date (Newest First)</option>
<option value="date_asc" <?php selected( $current_sort, 'date_asc' ); ?>>Date (Oldest First)</option>
<option value="title_asc" <?php selected( $current_sort, 'title_asc' ); ?>>Title (A-Z)</option>
<option value="title_desc" <?php selected( $current_sort, 'title_desc' ); ?>>Title (Z-A)</option>
<option value="price_asc" <?php selected( $current_sort, 'price_asc' ); ?>>Price (Low to High)</option>
<option value="price_desc" <?php selected( $current_sort, 'price_desc' ); ?>>Price (High to Low)</option>
<option value="rating_desc" <?php selected( $current_sort, 'rating_desc' ); ?>>Rating (High to Low)</option>
<option value="rating_asc" <?php selected( $current_sort, 'rating_asc' ); ?>>Rating (Low to High)</option>
</select>
<?php
foreach ( $_GET as $key => $value ) {
if ( $key !== 'sort_by' ) {
echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '">';
}
}
?>
</form>
<?php
}
meta_value
or meta_value_num
can be slower on large datasets, especially if the meta_key
is not indexed in your database. Consider using a persistent object cache or optimizing your database if you encounter performance issues.Integrating the Sorting Dropdown into Your Theme
To make the sorting options visible to your users, you need to call the display_sort_dropdown()
function (or display_sort_dropdown_with_meta()
) within your theme's template files. Common places include archive.php
, category.php
, tag.php
, or even index.php
if it serves as an archive.
1. Locate Theme Template File
Open your theme's archive.php
(or similar) file. If your theme doesn't have a specific archive template, you might need to add it to index.php
or a custom template.
2. Insert the Dropdown Function
Find a suitable location within the loop or just before it where you want the dropdown to appear. This is typically above the post listings. Add <?php display_sort_dropdown_with_meta(); ?>
.
3. Test Functionality
Save the file and navigate to an archive page on your site. You should now see the sorting dropdown. Select different options to confirm that the posts reorder correctly.