1

I need to add more arguments to the wp_query if they variables are !empty when passed by the shortcode. I am passing the name of a couple of custom field names to be used in the loop.

I want it to work like this: If custom_field_1 is !empty but custom_field_2 is empty, add the first array to the $args array. If custom_field_1 is !empty and custom_field_2 is !empty, add the second array to the $args array.

I feel that I am somewhere in the ballpark but it is not working properly. If I manually add each of the meta_queries to the $args array it returns the correct data.

Any help would be appreciated.

// Attributes
extract( shortcode_atts(
    array(
        'pagination' => 'true',
        'query' => '',
        'category' => '',
        'tag_name' => '',
        'custom_field_1' => '',
        'custom_field_2' => '',
        'relation_operator' => '',
        'number_posts' => '',
        'order_by'   => '',
        'order'     => '',
    ), $atts ));

$paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;

$custom_field_query = array ();

// if $custom_field_1 is not empty and $custom_field_2 is empty 
if (!empty($custom_field_1) && empty($custom_field_2) ) {
    array_push($custom_field_query, array (
        'meta_query' => array(
            array(
                'key'     => $custom_field_1,
                'value'   => '',
                'compare' => '!='
            ) ) ) );
} 

// if $custom_field_1 is not empty and $custom_field_2 is not empty
if (!empty($custom_field_1) && !empty($custom_field_2) ) {
    array_push($custom_field_query, array (
        'meta_query' => array(
            'relation' => $relation_operator,
            array(
                'key'     => $custom_field_1,
                'value'   => '',
                'compare' => '!=',
            ),
            array(
                'key'     => $custom_field_2,
                'value'   => '',
                'compare' => '!=',
            ) ) ) );    
} 

// if $custom_field_query has array custom_field_query gets added to $args
if(!empty($custom_field_query)){
    $args['custom_field_query'] = $custom_field_query;
}   

// WP_Query arguments
$args = array(
    'paged'                 => $paged,
    'post_type'             => array( 'page', ' post' ),
    'post_status'           => array( 'publish' ),
    'category_name'         => $category,
    'tag'                   => $tag_name,
    'category__in'          => $theCatId,       
    'posts_per_page'        => $number_posts,
    'order'                 => $order,
    'orderby'               => $order_by,
    );  

// The Query
global $wp_query,$paged,$post;
$my_query = new WP_Query( $args );
1
  • $args['custom_field_query'] isn't a valid query argument, that should be $args['meta_query']. Check out the php manual for working with associative arrays, array_push is not the function for that.
    – Milo
    Jul 24, 2017 at 0:22

1 Answer 1

3

I would suggest trying not to over-complicate the logic. You have the general thought process correct in your question. Assuming everything above works when you just add the meta_query logic to the query directly and run it, then your code should try to follow that same thought pattern.

You're accessing the globals - so list those out first. This will also make it so they are easy to reference later on when you need to come back to what you've done:

    // Globals.
    global $wp_query, $paged, $post;

Now you are getting the short code attributes, it's discouraged to use extract here, so I'd recommend just setting that to a variable:

Note: You will need to update the locations where you refer to the variables extracted with reference to your shortcode attributes array. I just named it $sc for this example.

    // Shortcode attributes.
    $sc = shortcode_atts(
        array(
            'pagination' => 'true',
            'query' => '',
            'category' => '',
            'tag_name' => '',
            'custom_field_1' => '',
            'custom_field_2' => '',
            'relation_operator' => '',
            'number_posts' => '',
            'order_by'   => '',
            'order'     => '',
        ),
        $atts
    );

Next, you are wanting to modify your WP_Query arguments if your conditions are met, so put your default query arguments next, $args:

Note: get_query_var accepts a default as the second argument passed, so you can cut out that conditional and cast to an int with the default param set (this is significantly faster than the logic used in the question and produces the same outcome [ie absint internally calling intval compared to casting to int]). I'd probably just stick this in your $args directly instead of set a variable for it.

    // WP_Query arguments
    $args = array(
        'paged'          => ( int ) get_query_var( 'paged', 1 ),
        'post_type'      => array( 'page', ' post' ),
        'post_status'    => array( 'publish' ),
        'category_name'  => $sc['category'],
        'tag'            => $sc['tag_name'],
        'category__in'   => $theCatId,       
        'posts_per_page' => $sc['number_posts'],
        'order'          => $sc['order'],
        'orderby'        => $sc['order_by'],
    );

Now you want to add your conditions and modify the arguments if certain things are met:

Note: You can use if ( ! empty( $custom_field_1 ) ) if you wish. I just find if ( $custom_field_1 ) easier to read/faster to write, but that's just personal preference.

    // custom_field_1 is populated.
    if ( $sc['custom_field_1'] ) {

        // custom_field_2 is populated.
        if ( $sc['custom_field_2'] ) {
            $args['meta_query'] = array(
                    'relation' => $sc['relation_operator'],
                    array(
                        'key'     => $sc['custom_field_1'],
                        'value'   => '',
                        'compare' => '!=',
                    ),
                    array(
                        'key'     => $sc['custom_field_2'],
                        'value'   => '',
                        'compare' => '!=',
                    ),
                )
            );

        // custom_field_2 is not populated.
        } else {
            $args['meta_query'] = array(
                array(
                    'key'     => $sc['custom_field_1'],
                    'value'   => '',
                    'compare' => '!=',
                ),
            );
        }
    }

Now you've modified the arguments as you desired, so create your query:

    // Custom query $my_query.
    $my_query = new WP_Query( $args );

I didn't see any reference to $theCatId, so I assume you're handling that somewhere else in your script. Things could also be written more efficiently than what I did from your example code, but either way, this should hopefully help point you in the right direction of getting your desired result.

All of the above together:

    // Globals.
    global $wp_query, $paged, $post;

    // Shortcode attributes.
    $sc = shortcode_atts(
        array(
            'pagination' => 'true',
            'query' => '',
            'category' => '',
            'tag_name' => '',
            'custom_field_1' => '',
            'custom_field_2' => '',
            'relation_operator' => '',
            'number_posts' => '',
            'order_by'   => '',
            'order'     => '',
        ),
        $atts
    );

    // WP_Query arguments
    $args = array(
        'paged'          => ( int ) get_query_var( 'paged', 1 ),
        'post_type'      => array( 'page', ' post' ),
        'post_status'    => array( 'publish' ),
        'category_name'  => $sc['category'],
        'tag'            => $sc['tag_name'],
        'category__in'   => $theCatId,       
        'posts_per_page' => $sc['number_posts'],
        'order'          => $sc['order'],
        'orderby'        => $sc['order_by'],
    );

    // custom_field_1 is populated.
    if ( $sc['custom_field_1'] ) {

        // custom_field_2 is populated.
        if ( $sc['custom_field_2'] ) {
            $args['meta_query'] = array(
                    'relation' => $sc['relation_operator'],
                    array(
                        'key'     => $sc['custom_field_1'],
                        'value'   => '',
                        'compare' => '!=',
                    ),
                    array(
                        'key'     => $sc['custom_field_2'],
                        'value'   => '',
                        'compare' => '!=',
                    ),
                )
            );

        // custom_field_2 is not populated.
        } else {
            $args['meta_query'] = array(
                array(
                    'key'     => $sc['custom_field_1'],
                    'value'   => '',
                    'compare' => '!=',
                ),
            );
        }
    }

    // Custom query $my_query.
    $my_query = new WP_Query( $args );
2
  • Thank you so much Tim. That worked perfect. It also explains a few other things that I was unsure of. Since you mentioned $theCatId, here are the additional lines of code used for that. $theCatId = get_term_by( 'slug', $category, 'category' ); $theCatId = $theCatId->term_id; If you know of a way I can streamline this, that would be amazing as well.
    – Jeronimo
    Jul 24, 2017 at 23:25
  • No problem, I'm glad it helped. The way you're getting the term ID seems perfectly fine!
    – Tim Elsass
    Jul 25, 2017 at 15:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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