Send Multiple Custom Field Values Through the URL

Basically, I’m trying to follow this tutorial to add an action to the pre_get_posts and create a custom meta_query so I can alter the query within the URL and display babies,children and home books like so:

http://website.com/books/?type=babies,children,home

Read More

I’m using the Advanced Custom Fields plugin for my custom fields and my custom field is called ‘type’ and is set up in WordPress as a Checkbox Field, so it accepts multiple values.

For the life of me, I can’t work out how to get it to display the queried posts.

function my_pre_get_posts( $query ) {
if( is_admin() ) { return; }

$meta_query = $query->get('meta_query');
    if( !empty($_GET['type']) ) {               
        $type = explode('|', $_GET['type']);    
        $meta_query[] = array(                          
            'key'       => 'type',
            'value'     => $type,
            'compare'   => 'IN',
        );
    }

$query->set('meta_query', $meta_query); // update the meta query args
return; // always return
}

Using 'compare' => 'LIKE' just returns random posts, using IN returns a blank results page.

Not sure if it’s to do with my $_GET['type'] parameter, which is supposed to be string.

Any help with solving this is appreciated. I’m on my 5th cup of coffee and the evening isn’t looking promising.

archive.book.php

$args = array(
'post_type'     => 'book',
'posts_per_page'    => 10,
);

$wp_query = new WP_Query( $args );
while( $wp_query->have_posts() ) {

    $wp_query->the_post();
    get_template_part( 'content', get_post_format() );
}

This normal loop:

<?php 
print_r( $wp_query->request );
if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();
        get_template_part( 'content', get_post_format() );
    } // end while
} // end if
?>

outputs this:

SELECT SQL_CALC_FOUND_ROWS blISt3rs871o_posts.ID FROM blISt3rs871o_posts WHERE 1=1 AND blISt3rs871o_posts.post_type = 'book' AND (blISt3rs871o_posts.post_status = 'publish' OR blISt3rs871o_posts.post_status = 'private') ORDER BY blISt3rs871o_posts.post_date DESC LIMIT 0, 10

Related posts

2 comments

  1. First, keep in mind that pre_get_posts is a hook that is run on every single query that WP runs, so be very, very careful when utilizing it. That said, it is absolutely the best tool for what you want to do, and certainly better than writing a separate custom query in the page template.

    I’ve added some additional conditions to the start of this function to make sure it is abandoned early if the query is: not for the main loop, running on an admin page, or if the ‘type’ query string is not present. You should add a few more conditions here to restrict it even further, e.g. if ( ! is_page( 'something' ) ) { return; } or if ( ! is_front_page() ) { return; }.

    That said, here is some sample code:

    /**
     * Add custom meta filter to main query on any page.
     *
     * @since  1.0.0
     *
     * @param  object $query WP Query object.
     */
    function wpse129223_custom_meta_query( $query ) {
    
        // If not on the main query, or on an admin page, bail here
        if ( ! $query->is_main_query() || is_admin() ) {
            return;
        }
    
        // If 'type' isn't being passed as a query string, bail here
        if ( empty( $_GET['type'] ) ) {
            return;
        }
    
        // Get the existing meta query, cast as array
        $meta_query = (array) $query->get('meta_query');
    
        // Convert 'type' into an array of types
        $types = explode( ',', $_GET['type'] );
    
        // Ensure that types aren't empty
        if ( is_array( $types ) && ! empty( $types ) ) {
    
            // Build a meta query for this type
            $meta_query[] = array(
                'key'     => 'type',
                'value'   => $types,
                'compare' => 'IN',
            );
    
            // Update the meta query
            $query->set( 'meta_query', $meta_query );
        } 
    
    }
    add_action( 'pre_get_posts', 'wpse129223_custom_meta_query' );
    

    This expects the query string to be comma-separated, as you presented it in your example, website.com/whatever/?type=one,two,three. In your code example you were looking for a pipe character, which is what @Foxsk8 was getting at in his comments.

  2. Here is code, that works.

    <?php
         $type = explode(',', $_GET['type']);
         $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
         $myquery = new WP_Query(array(
         'post_type' => 'building',
         'meta_query'=>array(
                array(
                    'key' => 'type',
                    'value' => $type,
                ),
    
            )
    
        ));
        if ($myquery->have_posts()) :
        while ($myquery->have_posts()) : $myquery->the_post();
    ?>
    <h1><?php the_title(); ?></h1>
    <?php the_content(); ?>
    <?php endwhile; endif; ?>
    

Comments are closed.