Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

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!

like image 373
HWD Avatar asked Jun 24 '15 21:06

HWD


People also ask

How to complete category and taxonomy query in WordPress?

Complete Category and Taxonomy Querying in WordPress 1 Preparing the Query with pre_get_posts. Before we get started, you might be wondering how to get the results of your custom taxonomy category query onto the screen. 2 Querying Categories. ... 3 Simple Taxonomy Queries. ... 4 Complex Taxonomy Queries. ...

Should you exclude specific results from your WordPress search results?

Being able to exclude specific results from a WordPress search can come in handy. The best-case scenario is that it saves you from having to install a search plugin. Usually, however, it will give you some control over who can find what on your website, and it’s up to you to make the most of it.

Is it possible to query custom taxonomies?

But in addition, custom taxonomies have their own specific syntax that can get pretty complicated depending on the needs of your query. In this article, we’ll take a comprehensive look at querying both categories as well as taxonomies.

How to exclude specific posts and pages from search results?

You can use a plugin to exclude specific posts and pages from your website’s search results. It’s called Search Exclude, and you can find it easily by navigating to Plugins > Add New in your website’s backend and typing its name in the search box. Once you find it, install and activate it.


1 Answers

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 );
like image 151
birgire Avatar answered Oct 20 '22 23:10

birgire