How To Exclude Results From Custom WordPress MySQL Query By Taxonomy Term

I only want to show posts which do not have the term ‘brand-slug’ for the taxonomy ‘product-brand’.

My current query doesn’t apply the filter:

Read More
SELECT DISTINCT * FROM $wpdb->posts AS p
  LEFT JOIN $wpdb->postmeta AS meta ON p.ID = meta.post_id
  LEFT JOIN $wpdb->term_relationships AS rel ON rel.object_id = p.ID
  LEFT JOIN $wpdb->term_taxonomy AS tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
  LEFT JOIN $wpdb->terms AS term ON tax.term_id = term.term_id
WHERE 1=1
    AND p.post_type = 'product' 
    AND p.post_status = 'publish' 
    AND p.post_title LIKE '%$trimmed%' OR (meta.meta_key = 'product_model' AND meta.meta_value LIKE '%$trimmed%') 
    AND (tax.taxonomy = 'product-brand' AND term.slug NOT IN ('$protected'))

Neither taxonomy or slug conditionals seem to be working in the above query.

Any help is appreciated!

Related posts

1 comment

  1. Notes:

    It looks like you’re not using $wpdb->prepare(), so you risk SQL injections.

    I also think you’re missing parentheses around the relevant OR parts, so you don’t end up displaying drafts, for example.

    Alternative:

    Instead of writing an hardcoded SQL query, we should be able to use the WP_Query class, with some modifications through hooks/filters.

    Here’s an example (PHP 5.4+):

    $args = [ 
        '_meta_or_like_title' => $trimmed,        // Our new custom argument!
        'post_type'           => 'product',
        'post_status'         => 'publish',
        'meta_query'          => [
            [
                'key'     => 'product_model',
                'value'   => $trimmed,            // Your meta value
                'compare' => 'LIKE'
            ]
        ],
        'tax_query'    => [
            [
                'taxonomy'  => 'product-brand',
                'field'     => 'slug',
                'terms'     => $protected,        // Your terms array
                'operator'  => 'NOT IN'
            ]
        ]
    ];
    

    where the custom _meta_or_like_title argument is supported by a slightly modified plugin I wrote for another question here.

    Plugin:

    <?php
    /**
     *  Plugin Name:   Meta OR LIKE Title query in WP_Query
     *  Description:   Activated through the '_meta_or_like_title' argument of WP_Query 
     *  Plugin URI:    http://stackoverflow.com/a/31241416/2078474
     *  Plugin Author: Birgir Erlendsson (birgire)
     *  Version:       0.0.1
     */
    
    add_action( 'pre_get_posts', function( $q )
    {
        if( $title = $q->get( '_meta_or_like_title' ) )
        {
            add_filter( 'get_meta_sql', function( $sql ) use ( $title )
            {
                global $wpdb;
    
                // Only run once:
                static $nr = 0; 
                if( 0 != $nr++ ) return $sql;
    
                // Modify WHERE part:
                $sql['where'] = sprintf(
                    " AND ( %s OR %s ) ",
                    $wpdb->prepare( 
                        "{$wpdb->posts}.post_title LIKE '%%%s%%'", 
                         $wpdb->esc_like( $title ) 
                    ),
                    mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
                );
                return $sql;
            });
        }
    }, PHP_INT_MAX );
    

Comments are closed.