4

I want to search for posts with WP_Query() and select only posts that begin with a specific letter. I found a bunch of old posts with filters that were pre-4.4, but since 4.4 there is a title search added to the WP_Query function.

 $q = new WP_Query( array('post_type'=>'post','title'=>'This Song Title') );

This will return only exact matches of posts with the title "This Song Title".

What I would like to do is return all posts that start with, in this example, the letter 'T'

I also found this post, which was never really answered. It's the accepted answer, but I don't see how it answers the question at all. How to limit search to first letter of title?

Other query features like comment and meta searches have a 'compare' for adding LIKE% to queries, but title does not seem to.

4

It's not possible with WP_Query directly out-of-the-box, but by using the posts_where filter to look for a custom argument on WP_Query, it is possible to add this functionality.

Assuming starts_with is the name of the argument we want to use, we can filter posts_where to add a WHERE clause limiting results to those that begin with the given value if starts_with has been set on the query:

function wpse_298888_posts_where( $where, $query ) {
    global $wpdb;

    $starts_with = $query->get( 'starts_with' );

    if ( $starts_with ) {
        $where .= " AND $wpdb->posts.post_title LIKE '$starts_with%'";
    }

    return $where;
}
add_filter( 'posts_where', 'wpse_298888_posts_where', 10, 2 );

With this filter added, we can query posts like this:

$query = new WP_Query( array(
    'starts_with' => 'M',
) );

That will return all posts beginning with "M".

If you want to be able to filter the main query, you can also use this argument in pre_get_posts:

function wpse_298888_pre_get_posts( $query ) {
    if ( $query->is_main_query() ) {
        $query->set( 'starts_with', 'M' );
    }
}
add_action( 'pre_get_posts', 'wpse_298888_pre_get_posts' );
  • 2
    This works perfect, but I made one adjustment that may also help others. I used REGEXP instead of LIKE so I could feed the range 0-9 for titles that start with numbers into a single group. $where .= " AND $wpdb->posts.post_title REGEXP '^$starts_with'"; – Mark Mar 26 '18 at 19:07
  • Would it be possible to do this the other way around, where you could select all of the posts and/or pages that don't start with a particular letter/string? I want to exclude specific pages whose titles start with the same word from the search results, but want to keep it open-ended in case more of these are created as opposed to using static IDs. These aren't posts, so they don't have tags or categories. – Yami Medina Dec 18 '18 at 21:19
  • 1
    Just change the LIKE in the first block of code to NOT LIKE. – Jacob Peattie Dec 18 '18 at 23:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.