Custom Post Type Query multiple Taxonomy Terms

Query Arguments:

If $input_terms is the input array of term slugs, then you should be able to use (if I understand the question correctly):

$property = [
    'post_type'         => 'properties',
    'paged'             => $paged,
    'tax_query'         => [
        [
            'taxonomy'  => 'features',
            'field'     => 'slug',
            'terms'     => $input_terms,
            'operator'  => 'AND',
        ]
    ],
];

where we added a missing array in the tax query.

Validation:

We should validate the input terms first.

Here are some examples:

  • Check the maximum number of allowed terms:

    $valid_input_terms_max_count = count( $input_terms ) <= 4;
    
  • Check the minimum number of allowed terms:

    $valid_input_terms_min_count = count( $input_terms ) >= 1;
    
  • Check if they input terms slugs exists (assumes non-empty input array):

    $valid_input_terms_slugs = array_reduce( 
        (array) $input_terms, 
        function( $carry, $item ) { 
            return $carry && null !== term_exists( $item, 'features' ); 
        }, 
        true 
    );
    

    where we collect term_exists() for all the terms into a single boolean value.

  • We could also match the input slugs against a predefined array of slugs

Generated SQL:

Here’s a generated SQL query for two existing term slugs in $input_terms:

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID 
FROM wp_posts  
WHERE 1=1  AND ( 
  (
        SELECT COUNT(1)
        FROM wp_term_relationships
        WHERE term_taxonomy_id IN (160,161)
        AND object_id = wp_posts.ID
    ) = 2
) 
AND wp_posts.post_type="properties" 
AND (wp_posts.post_status="publish" OR wp_posts.post_status="private") 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0, 10

Hope you can adjust this to your needs.