0

I have a method that works. However, it's not very optimal and limits WP_Query's functionality (recently with pagination).

I saw a similar question/issue, but the answer provided is the current concept I'm trying to avoid (and it didn't consider different terms for each post type). Using Query Posts With Multiple Post Types And A Taxonomy

Is it possible to reduce this to 1 instance of WP_Query?

Would WPDB even be able to?

I tried to clean and reduce what I have to use as an example. This is also a recursive function.

/**
 * Query WP
 *
 * Queries multiple instances of this function if there is more than one
 * query_str.
 *
 * @param array   $query_str_array Multi-dimensional query_str array.
 * @param boolean $repeated This function repeated.
 * @return mixed WP_Query class if unrepeated, otherwise array of post_IDs.
 */
function query_wp( $query_str_array, $repeated = false ) {
    $post_in_ids     = array();
    $post_not_in_ids = array();

    /*
     * If this is the first instance of this function.
     * Then repeat this function if more queries are present, and
     * query/collect the posts IDs.
     */
    if ( false === $repeated ) {
        /*
         * This is the Initial and Final Query. This is used to collect IDs first
         * with 1 or more query_str (that couldn't be consolidated/merged), and
         * then do one last query here to return. This allows sorting with other
         * custom post types that couldn't be queried together, and allows
         * compatibility with posts_in & posts_not_in.
         */

        $post_in_ids = array_merge( query_wp( $query_str_array, true ) );
        $query_str   = array_shift( $query_str_array );

        // Filter out excluded posts.
        foreach ( $query_str['post__not_in'] as $post_not_value ) {
            foreach ( $post_in_ids as $key => $post_in_value ) {
                if ( $post_in_value === $post_not_value ) {
                    unset( $post_in_ids[ $key ] );
                }
            }
        }
        $post_in_ids = array_merge( $post_in_ids );

        // Prevent defaulting when there's no posts.
        if ( empty( $post_in_ids ) ) {
            $post_in_ids[] = 0;
        }

        // Set FINAL query_str with post IDs.
        $final_query_str = array(
            'post__in'            => $post_in_ids,
            'post_type'           => 'any',
            'posts_per_page'      => $query_str['posts_per_page'],
            'offset'              => $query_str['offset'],
            'nopaging'            => ( -1 === $query_str['posts_per_page'] ) ? true : false,
            'order'               => $query_str['order'],
            'orderby'             => $query_str['orderby'],
            'ignore_sticky_posts' => $query_str['ignore_sticky_posts'],
        );

        // Get FINAL Query Object.
        $final_query_obj = new WP_Query( $final_query_str );

        return $final_query_obj;
    } else {
        // Shift the args when repeating this method / function.
        // If more args exist, then repeat this function.
        // Merge returned post ids for pre-final query.
        $query_str = array_shift( $query_str_array );
        if ( ! empty( $query_str_array ) ) {
            $post_in_ids = array_merge( query_wp( $query_str_array, true ), $post_in_ids );
        }

        // Add Terms for Any/All ( value = 0 ).
        if ( ! empty( $query_str['tax_query'] ) ) {
            foreach ( $query_str['tax_query'] as $k1_index => $tax_arr ) {
                if ( 'relation' === $k1_index ) {
                    continue;
                }

                if ( 0 === $tax_arr['terms'][0] && 1 === count( $tax_arr['terms'] ) ) {
                    $terms_args = array(
                        'taxonomy' => $tax_arr['taxonomy'],
                        'fields'   => 'ids',
                    );

                    $tax_arr['terms'] = get_terms( $terms_args );

                    $query_str['tax_query'][ $k1_index ] = $tax_arr;
                } else {
                    $query_str['tax_query'][ $k1_index ] = $tax_arr;
                }
            }
        }

        // Since post__in and post__not_in don't mix at all. The 2 variables
        // are stored seperately.
        if ( ! empty( $query_str['post__not_in'] ) && 0 < $query_str['posts_per_page'] ) {
            // Removed at final.
            // $post_not_in_ids = $query_str['post__not_in'];
            $query_str['posts_per_page'] += count( $query_str['post__not_in'] );
        }
        unset( $query_str['post__not_in'] );

        if ( ! empty( $query_str['post__in'] ) ) {
            $post_in_ids = array_merge( $post_in_ids, $query_str['post__in'] );
        }
        unset( $query_str['post__in'] );

        // If Posts Per Page is set to -1/Unlimited, then set nopaging to true.
        if ( -1 === $query_str['posts_per_page'] ) {
            $query_str['nopaging'] = true;
        }

        if ( isset( $query_str['offset'] ) ) {
            $query_str['offset'] = 0;
        }

        // Sets the query string to just query IDs.
        $query_str['fields'] = 'ids';
        $query_obj           = new WP_Query( $query_str );

        // Collect an array of Post IDs.
        $post_ids = array();
        if ( ! empty( $query_obj->posts ) ) {
            foreach ( $query_obj->posts as $i => $post_id ) {
                $post_ids[] = intval( $post_id );
            }
        }

        $post_ids = array_merge( $post_ids, $post_in_ids );

        wp_reset_postdata();
        return $post_ids;
    }// End if().
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.