Search code examples
phpwordpressmeta-query

How to allow the URL to alter the query using multiple parameters?


I want to display data based on query parameters passed through URL: https://example.com/?make=nike&model=shox&colour=white&body_type=slim.

  1. I can browse "nike" stock by accessing https://example.com/?make=nike.

  2. I can browse "nike shox" by accessing https://example.com/?make=nike&model=shox.

  3. I can't browse "nike shox white" https://example.com/?make=nike&model=shox&colour=white as I'm getting mixed results not related with query.

  4. I can't browse "nike shox white slim" https://example.com/?make=nike&model=shox&colour=white&body_type=slim as I'm getting mixed results not related with query.

  5. I can access "white" https://example.com/?colour=white.

  6. I can access "slim" https://example.com/?body_type=slim.

I'm using following code:

if ( isset( $query->query_vars['post_type'] ) && $query->query_vars['post_type'] == 'post' ) {

    // allow the url to alter the query
    if ( isset( $_GET['make'] ) ) {

        $query->set( 'meta_key', 'make' );
        $query->set( 'meta_value', $_GET['make'] );

    } 

    if ( isset( $_GET['model'] ) ) {

        $query->set( 'meta_key', 'model' );
        $query->set( 'meta_value', $_GET['model'] );

    } 
    if ( isset( $_GET['colour'] ) ) {

        $query->set( 'meta_key', 'colour' );
        $query->set( 'meta_value', $_GET['colour'] );

    }

    if ( isset( $_GET['body_type'] ) ) {

        $query->set( 'meta_key', 'body_type' );
        $query->set( 'meta_value', $_GET['body_type'] );

    } 

}

What am I doing wrong? Cheers!


Solution

  • Each time you call $query->set( 'key', 'value' ); the previous value gets overwritten.

    If I am guessing right, the parameters ?make=nike&model=shox are only "working" because shox is the last parameter, and there are only shox models with make=nike.

    You could do something like this:

    $metaQuery = [];
    
    if ( isset( $_GET['make'] ) ) {
        $metaQuery[] = [
            'key'     => 'make',
            'value'   => $_GET['make'],
            'compare' => '=',
        ];
    }
    if ( isset( $_GET['model'] ) ) {
        $metaQuery[] = [
            'key'     => 'model',
            'value'   => $_GET['model'],
            'compare' => '=',
        ];
    }
    if ( isset( $_GET['colour'] ) ) {
        $metaQuery[] = [
            'key'     => 'colour',
            'value'   => $_GET['colour'],
            'compare' => '=',
        ]; 
    }
    if ( isset( $_GET['body_type'] ) ) { 
        $metaQuery[] = [
            'key'     => 'body_type',
            'value'   => $_GET['body_type'],
            'compare' => '=',
        ];
    }
    
    $query->set( 'meta_query', $metaQuery );
    

    You could do it even cleaner using a foreach() loop on the $_GET superglobal.

    $metaQuery = [];
    
    foreach ( $_GET as $metaKey => $metaValue ) {
        $metaQuery[] = [
            'key'     => $metaKey,
            'value'   => $metaValue,
            'compare' => '=',
        ];
    }
    
    if ( count( $metaQuery ) > 0 ) {
        $query->set( 'meta_query', $metaQuery );
    }