Support

Account

Home Forums General Issues Post Object – Query filter for both title and/or meta value

Solving

Post Object – Query filter for both title and/or meta value

  • Hello!

    I’ve added a couple of extra fields for my Post Object dropdown, currently I’m showing Post title and two other fields, Client (ACF text field) and Director (An associated posts title).

    This is easily added like this

    add_filter('acf/fields/post_object/result/key=field_595cda4b4dbfb', function( $title, $post, $field, $post_id ) {
    
        $client = get_field('client', $post->ID);
        if ($client) {
            $title .= ' (' . $client . ')';
        }
    
        $director_post = get_field('director', $post->ID);
        $director = $director_post->post_title;
        if($director) {
            $title .= ' by '. $director  .'';
        }
    
        return $title;
    
    }, 10, 4);

    Producing this result
    Post Object Dropdown

    So far so good. But as Client and Director shows up, the user might think that you can search for Title/Client/Director when looking for posts. This is not possible with the default settings.
    Post Object Dropdown - Not Found

    Using the query filter (acf/fields/post_object/query/key=field_595cda4b4dbfb), I reckon I should be able to add additional search parameters, allowing to look for meta value. But if I add this, it will look for posts with that meta value specifically, excluding any other post.

    add_filter('acf/fields/post_object/query/key=field_595cda4b4dbfb', function ( $args, $field, $post_id ) {
    
        $meta_query = array();
        $meta_query[] = array(
            'key' => 'client',
            'value' => 'Apple', // $args['s']
            'compare' => 'LIKE'
        );
    
        $args['meta_query'] = $meta_query;
        return $args;
    
    }, 10, 3);

    (Interestingly, $args[‘s’] does not work in this context – Only hardcoding ‘Apple’ will bring up results, using $args[‘s’] will show “Not matches found” – Why?)

    While looking for a solution to be able to look for both title and meta value I found this very helpful thread: https://wordpress.stackexchange.com/a/208939/2830

    So in the end I have this piece of code

    /**
    * Make Client and Director searchable in Post Object Selector
    */
    
    add_filter('acf/fields/post_object/query/key=field_595cda4b4dbfb', function ( $args, $field, $post_id ) {
    
        $meta_query = array();
        $meta_query[] = array(
            'key' => 'client',
            'value' => $args['s'],
            'compare' => 'LIKE'
        );
    
        if(count($meta_query) > 1) {
            $meta_query['relation'] = 'OR';
        }
    
        $args['_meta_or_title'] = $args['s'];
        $args['meta_query'] = $meta_query;
    
        return $args;
    
    }, 10, 3);
    
    /**
    * Modify query to search either title and/or meta values
    */
    
    add_action( 'pre_get_posts', function( $q ) {
        if( $title = $q->get( '_meta_or_title' ) ) {
            add_filter( 'get_meta_sql', function( $sql ) use ( $title )
            {
                global $wpdb;
    
                // Only run once:
                static $nr = 0;
                if( 0 != $nr++ ) return $sql;
    
                // Modified WHERE
                $sql['where'] = sprintf(
                    " AND ( %s OR %s ) ",
                    $wpdb->prepare( "{$wpdb->posts}.post_title like '%%%s%%'", $title),
                    mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
                );
    
                return $sql;
            });
        }
    });

    However, it’s still not working, I only get matches while searching for the post title.
    Post Object - Post title
    Post Object - Client not found

    Anyone that’s able to give some advice?

  • Here’s some debug information from the ajax call
    ajax debug

  • I know this post is over a year old, I was wondering if you ever managed to get this search functionality working.

  • Modifying the query to search for values in the title OR in meta fields is not an easy thing to do and cannot be done with the ACF filters alone. It requires making alterations to the “WHERE” portion of the query after it is constructed. http://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

  • I couldn’t get any of the published methods working with ACF. Using the adambelee link, the WHERE clause was always empty. However, got it working by combining ACF query filter with a WP WHERE override to turn the search AND meta into search OR meta.

    Essentially, WP Query is missing a meta_query_relation option (and tax_query_relation for that matter) and this code adds one!

    /*
     * Allow breaker search by make/model or VRN. Requires two parts:
     * 1. Inject meta-query for VRN, plus custom query param to trigger part 2
     * 2. Modify final query to OR the meta_query instead of AND
     * Basically add the missing WordPress query_var!
     */
    
    // Part 1
    add_filter('acf/fields/post_object/query/name=part_breaker', 'motor_vrn_search_query1', 10, 3);
    function motor_vrn_search_query1( $args, $field, $post_id) {
    
    	if (isset($args['s'])) { 
    		$args['meta_query'] = array(
    			'relation' => 'OR',
    			array(
    				'key' => 'motor_id_motor_vrn',
    				'value' => $args['s'],
    				'compare' => 'LIKE'),
    		);
    		$args['_meta_query_relation'] = 'OR'; // Custom query param
    	}
    	
    	return $args;
    }
    
    // Part 2: Modify the search query with posts_where
    add_filter( 'posts_where', 'motor_vrn_search_query2', 10, 2);
    function motor_vrn_search_query2( $where, $query) {
        global $pagenow, $wpdb;
    
    	$mq_relation = (isset($query->query_vars['_meta_query_relation']) ? $query->query_vars['_meta_query_relation'] : '');
    	if ($mq_relation === 'OR') { // WordPress defaults to AND
            $where = preg_replace(
                "/\)\)\)\s*AND \(\s*\(\s*".$wpdb->postmeta.".meta_key/",
                "))) OR (( ".$wpdb->postmeta.".meta_key",
    			$where
    		);
        }
    
        return $where;
    }
    
Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.

We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.