0

I'm building a search in WordPress. I look for a custom_post_type in combination with several custom taxonomys and metadatas.

custom_post_type: vehicle

taxonomys: brand, fueltype, ...

metadata: price, mileage, ...

I have a form to send the request to my archive.php - submits the data fine (i verified with $_GET).

The archive.php recieves the submited data and prepares a query for a loop (which is also in archive.php).

Every aspect of my submited form data (post_type, tax_query, meta_query) performs very well on/in my archive.php - when i use them single. So i can't combine tax_query and meta_query. When i use both in my code, it just shows/filters my loop with tax_query. If i delete tax_query from my code meta_query works/filtering with my loop.

But how to combine them? I know this "problem" is common.

I searched half of the web. There are a lot of questions on stackexchange, but no real answers (i found). Also the WordPress Codex gives no example for a combined code.

So a solution is needed. Any ideas?

I would prefer a way to combine them with just a regular order. I saw "tax_and_meta" and "tax_or_meta" for wp_query in one, two examples, (http://mycodeknowledge.blogspot.com/2017/02/combined-taxquery-and-meta-query-of.html) tried in several ways, but seems not to help me anyway.

I could/would maybe change the metadata to taxonomys (i had this idea and did), but as a standard i don't have an operator like "<" or ">" with tax_query, as i have with meta_query. So my idea failed, because i have to compare prices (saved as metadata)... Any idea how compare numeric values with taxonomy would be an other solution.

Next possible solution > but i don't prefer, cause i don't speak/write mysql very well. I saw/know it's possible to transform my arguments in a mysql query to ask the database directly. I saw one or two examples (and it seems to solve the situation http://zanematthew.com/wordpress-advanced-meta-query-using-wp_query/), but i can't understand/handle the code.

I really have to solve this thing. Do you have any ideas? Or any questions? Thanks a lot for your thinking about!

My form:

<form role="search" method="GET" id="searchform" action="<?php echo esc_url( home_url( '/cars/' ) ); ?>">
        <label for="model"><?php _e( 'Brand' ); ?></label>
        <?php wp_dropdown_categories( 'class=postform w100&depth=1&name=model&option_none_value=&show_count=1&show_option_none=Any&taxonomy=model&value_field=slug&hierarchical=1' ); ?>
        <label class="w100" for="price_max"><?php _e( 'Price' ); ?></label>
        <input id="price_min" class="w50 left" type="text" name="price_min" placeholder="Min price" />
        <input id="price_max" class="w50 left" type="text" name="price_max" placeholder="Max price" />
        <label for="fueltype"><?php _e( 'Fuel type' ); ?></label>
        <?php wp_dropdown_categories( 'class=postform w100&hierarchical=1&option_none_value=&name=fueltype&show_option_none=Any&taxonomy=fueltype&value_field=slug' ); ?>
        <div class="clear"></div>
        <input type="hidden" value="vehicle" name="post_type" />
        <input class="right" type="submit" id="searchsubmit" value="Search" />
        <div class="clear"></div>
    </form>

My archive.php:

    <?php $args = array(
        'post_type'              => $_GET['post_type'],
        'tax_query'              => array(
            array(
                'taxonomy'         => 'model',
                'terms'            => $_GET['model'],
                'field'            => 'slug',
            ),
            array(
                'taxonomy'         => 'fueltype',
                'terms'            => $_GET['fueltype'],
                'field'            => 'slug',
            ),
        ),
        'meta_query'             => array(
            array(
                'key'     => '_price',
                'value'   => $_GET['price_max'],
                'compare' => '<',
                'type'    => 'NUMERIC',
            ),
        ),
    );
get_header(); ?>
    <div id="primary" class="content-area">
        <main id="main" class="site-main" role="main">
        <div id="response"></div>
            <?php $query = new WP_Query( $args );
            if ( $query->have_posts() ) : ?>
                <header class="page-header">
                    <?php the_archive_title( '<h1 class="page-title">', '</h1>' );
                    the_archive_description( '<div class="archive-description">', '</div>' ); ?>
                </header><!-- .page-header -->
                <?php /* Start the Loop */
                while ( $query->have_posts() ) : $query->the_post();
                    /*
                     * Include the Post-Format-specific template for the content.
                     * If you want to override this in a child theme, then include a file
                     * called content-___.php (where ___ is the Post Format name) and that will be used instead.
                     */
                    get_template_part( 'template-parts/loop', get_post_type() );
                endwhile;
                wp_reset_postdata();
                the_posts_navigation();
            elseif ( have_posts() ) : ?>
                <header class="page-header">
                    <?php the_archive_title( '<h1 class="page-title">', '</h1>' );
                    the_archive_description( '<div class="archive-description">', '</div>' ); ?>
                </header><!-- .page-header -->
                <?php /* Start the Loop */
                while ( have_posts() ) : the_post();
                    /*
                     * Include the Post-Format-specific template for the content.
                     * If you want to override this in a child theme, then include a file
                     * called content-___.php (where ___ is the Post Format name) and that will be used instead.
                     */
                    get_template_part( 'template-parts/loop', get_post_type() );
                endwhile;
                wp_reset_postdata();
                the_posts_navigation();
            else :
                get_template_part( 'template-parts/content', 'none' );
            endif; ?>
        </main><!-- #main -->
    </div><!-- #primary -->
<?php if($_POST['post_type'] = 'vehicle')get_sidebar('cars');
get_footer();
  • 1
    I would note that post meta queries are super super expensive, it would be orders of magnitude faster if you instead rounded the price max to the nearest $10 or $100 and used a taxonomy with terms such as $80-99 or $100-200, or even a tag named $100 that had every product less than $100 in it. Otherwise it'll involve a table scan and a temporary table, which if you have a lot of products ( 100's ), it could be enough to bring your site down under mild load (5-10 concurrent users ), and at the same time giving slow page load speeds – Tom J Nowell Sep 4 '17 at 18:01
  • Hey Tom, thanks. Right, it's payload to handle. I like your idea. For search/loop use an taxonomy like 10-50, 51-100,... But i have to give a specific price like 120800000, too. Do you have an idea to use your idea with taxonomys in search (to solve the tax&meta-problem), but to compare with values in metadata? A workaround/hack or what? When i have a car, i can't give a price like 80.000.000-90.000.000. Need it fix. When my search is 10.000.000 - 300.000.000: this is a huge range. How to include the taxonomys in this range? tax_query doesn't have a compare/between/something like this. – wellseo Sep 4 '17 at 18:39
  • tax and meta queries work ok together, there is no special way they need to be combined. I suggest inspecting the query after you run it with <pre><?php print_r($query); ?></pre>, there you will see how the query is parsed and the generated SQL being sent to the database. I've tested it myself with two taxonomies and a similar meta comparison, using latest WordPress and 2016 theme and no plugins, the expected posts are returned from the query. – Milo Sep 4 '17 at 22:49
  • Ok Milo, you gave me the way to vertify und to see more details. Thanks a lot. Now it makes combinations out of all my tax & meta-values. Fine. It just seems like a problem with if/else/elseif when i (not) try to include the (not) given values. So just a problem with if/else... Milo, thanks a lot. I will do further research, correct the code and serve my solution here. At the moment i have to fill out all values. Otherwise the loop/combination fails... I have a few examples how to set if is empty and so on... – wellseo Sep 5 '17 at 14:37

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.