Search code examples
phpwordpresswordpress-rest-api

How do I filter wordpress rest api by any articles that contain the search term in the title?


Our wordpress installation uses the REST API from the backend to find articles. Currently, the query seems to be returning any articles that include any of the words in any fields. We're trying to change this so that it only returns articles that contain the search term in the title. For example, if the search term is "this is the title", then only articles that contained that exact phrase in the title would be returned.

I believe that what is required to do this is to create a custom filter for WP_Query, install the WP Rest Filter plugin to allow filtering via REST, and add the custom filter to the query. But I'm not sure how to implement that.

I see in this post https://wordpress.stackexchange.com/questions/286081/how-to-filter-my-search-in-post-if-contains-a-word-in-title-content-or-excerpt/286083#286083 how a WP_Query filter can be added. What I don't get from the solution posted there (in the section starting with "Well in the meantime, I found the solution", is where 'search_prod_title' is being provided. It is checked in this line below, but I don't see where that was set.

    if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {

The other part I don't get is how to choose the custom filter in the call the REST API. Here's where we currently call the REST API:

    $( '#article-assign' ).select2( {
        minimumInputLength: 3,
        ajax: {
            delay: 300,
            url: window.CFEwpApiSettings.root + 'wp/v2/posts',
            data: function( params ) {
                let query = {
                    _embed: true,
                    search: params.term
                };

                if ( articleIds.join( ',' ) !== '' ) {
                    query.exclude = articleIds.join( ',' );
                }

                return query;
            },

Does anyone know how I should modify the URL for the REST call (or the query if that's where it belongs) to use the custom filter?

Thank you for any help you can provide.

UPDATE: I've been able to get wp_query working properly with this:

    add_filter( 'posts_where', function ( $where, \WP_Query $q ) 
    {
            global $wpdb;
            $query_by_title = $q->get( 'queryByTitle' );
            if ( $query_by_title = $q->get( 'queryByTitle' ) ) {
                $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( $wpdb->esc_like( $query_by_title ) ) . '%\'';
            }
            return $where;    

    }, 10, 2 ); // Note the priority 10 and number of input arguments is 2

This works beautifully when I call it from PHP like this:

    $query = new WP_Query( array( 'queryByTitle' => 'hmi' ) );

Now I'm trying to figure out how I can pass that argument to PHP from JavaScript. I'm using the WP Rest Filter plugin to allow filtering, but I'm not sure how to specify the new argument of 'queryByTitle'. I was trying things like:

/wp-json/wp/v2/posts/?filter[meta_key]=queryByTitle&filter[meta_value]=words_to_find

But that doesn't work. Any idea how the REST API can accept the custom argument?


Solution

  • I figured it out. To get this working, I needed to add the argument to rest_query_vars with this:

        function wpse_20160526_rest_query_vars( $valid_vars ) {
            $valid_vars = array_merge( $valid_vars, array( 'queryByTitle' ) );
            return $valid_vars;
        }
    
        add_filter( 'rest_query_vars', 'wpse_20160526_rest_query_vars', PHP_INT_MAX, 1 );
    

    After that, this URL worked: /wp-json/wp/v2/posts?filter[queryByTitle]=some-text