Sort a WordPress post list without replacing the main query

Use a separate WP_Query for an alphabetical list, escape its output and restore the original post context afterwards.

An alphabetical list is a useful fit for a directory, glossary or collection of guides. It should not accidentally replace the query that WordPress uses to decide which page the visitor is on.

Use a separate query for a separate list

Put this inside a WordPress template or a server-rendered plugin callback. It lists ten published posts by title and breaks identical-title ties by ID:

<?php
$listing = new WP_Query([
    'post_type' => 'post',
    'post_status' => 'publish',
    'posts_per_page' => 10,
    'orderby' => ['title' => 'ASC', 'ID' => 'ASC'],
    'ignore_sticky_posts' => true,
    'no_found_rows' => true,
]);

if ($listing->have_posts()) {
    echo '<ul>';
    while ($listing->have_posts()) {
        $listing->the_post();
        echo '<li><a href="' . esc_url(get_permalink()) . '">'
            . esc_html(get_the_title()) . '</a></li>';
    }
    echo '</ul>';
}
wp_reset_postdata();

no_found_rows avoids calculating a total that this short list never uses. Remove it if you add pagination and need the total page count. Keep a deliberate item limit instead of loading every post on each request.

When you mean the archive itself

Use pre_get_posts to alter the main archive query, with explicit checks for the intended archive, is_main_query() and !is_admin(). A second query is for an extra list; changing the main query is for changing the archive itself.

Avoid query_posts(): it changes the global query and makes pagination and template behavior harder to reason about. If visitors can choose a sort order, map a small list of allowed choices to fixed query arguments rather than passing arbitrary URL parameters into the query.

References: WP_Query and pre_get_posts.

Original version4 July 2013

Kept here for reference and earlier links. The updated guide above is the recommended starting point; older code may depend on retired services or different software versions.

This Code Byte provides a very simple & cheeky/lazy way of creating filters to query certain post types/fields and sort them.

Within WordPress admin you can of course filter your content by clicking on a field like so:
wordpress-filter-queries

You will then notice your url changes to:
wp-admin/edit.php?orderby=title&order=asc

Although this is a PHP GET request, it's actually usable within your theme to set up specific queries, like sorting by a certain field, or post/page type.

This example will query posts and sort them by their Title in Ascending order:

<?php query_posts( 'orderby=title&order=asc' ); ?>

Of course, this is very simple, but sometimes a little easier than trying to remember or find out the field name you want to sort by.

Keep exploring

A couple more useful notes.