Home » Wordpress » WordPress meta query with multiple key value pairs and relations

WordPress meta query with multiple key value pairs and relations

Posted by: admin February 26, 2018 Leave a comment

Questions:

I have the following problem.
On my WordPress page there are small sticky posts and one big sticky post, this is all fine. But there are also regular posts and I need to not display the posts that are marked as sticky or big sticky with a meta value.

I need to query for value is not true or doesn’t exist for home_post key and value is not true or doesn’t exist for big_home_post key.

The code I came up with is the following:

'meta_query' => array(
    'relation' => 'AND',
    array(
        'relation' => 'OR',
        array(
            'key' => 'big_home_post',
            'value' => true,
            'compare' => '!='
        ),
         array(
            'key' => 'big_home_post',
            'value' => true,
            'compare' => 'NOT EXISTS'
        ),
    ),
    array(
        'relation' => 'OR',
        array(
            'key' => 'home_post',
            'value' => true,
            'compare' => '!='
        ),
         array(
            'key' => 'home_post',
            'value' => true,
            'compare' => 'NOT EXISTS'
        ),
    ),
),

The code is not working.

Maybe the multidimensional array is not built correctly or WordPress doesn’t support this at all.

All help is appreciated

Answers:

Hüseyin BABAL’s answer is outdated. As codex states:

Starting with version 4.1, meta_query clauses can be nested in order to construct complex queries.

So meta_query value like in question would work.

Codex: Custom Field Parameters

Questions:
Answers:

It is not possible to use nested array in meta_query. You need to write your own query for that. I suggest you to following code to achieve your target;

$query = new WP_Query( array(
    'custom_meta_query_enabled' => true,
) );

add_filter( 'posts_join', 'custom_meta_query', 10, 2 );
function custom_meta_query( $join, $query ) {
    if ( empty( $query->query_vars['custom_meta_query_enabled'] ) )
        return $join;

    global $wpdb;
    $new_join = "
        INNER JOIN {$wpdb->postmeta} wppm ON 1=1
            AND wppm.post_id = {$wpdb->posts}.ID
            AND (wppm.meta_key != 'big_home_post' OR (wppm.meta_key = 'big_home_post' AND wppm.meta_value != true)
            AND (wppm.meta_key != 'home_post' OR (wppm.meta_key = 'home_post' AND wppm.meta_value != true)
    ";
    return $join . ' ' . $new_join;
}

Simply, I have put a control called custom_meta_query_enabled. If you set this field in your WP_Query to true, system query will be overrided with custom join query. In order to use this, you can put it in functions.php