Cómo excluir resultados de una consulta MySQL personalizada de WordPress por término de taxonomía

4 minutos de lectura

Solo quiero mostrar publicaciones que no haga tienen el término ‘marca-babosa’ para la taxonomía ‘producto-marca’.

Mi consulta actual no aplica el filtro:

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'))

Ni la taxonomía ni los condicionales de slug parecen estar funcionando en la consulta anterior.

¡Cualquier ayuda es apreciada!

avatar de usuario
birgire

Notas:

Parece que no estás usando $wpdb->prepare()por lo que corre el riesgo de inyecciones de SQL.

También creo que le faltan paréntesis alrededor de las partes OR relevantes, por lo que no termina mostrando borradores, por ejemplo.

Alternativa:

En lugar de escribir una consulta SQL codificada, deberíamos poder usar el WP_Query clase, con algunas modificaciones a través de ganchos/filtros.

Aquí hay un ejemplo (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'
        ]
    ]
];

donde la costumbre _meta_or_like_title El argumento está respaldado por un complemento ligeramente modificado que escribí para otro pregunta aquí.

Enchufar:

<?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 );

  • Escribí exactamente el mismo enfoque (que abandoné a la mitad) ya que me quedé atascado con el filtrado donde buscas publicaciones por título o campo personalizado. en realidad fui el posts_* forma de filtro. Me gusta tu enfoque personalizado mejor que el mío 🙂

    – Pieter Goosen

    6 de julio de 2015 a las 9:26

  • necesitamos de alguna manera tener en nuestras manos toda la metaconsulta, por lo que el posts_* Los filtros no son tan adecuados como los get_meta_sql filtrar. Pero tal vez hay una manera con el posts_* filtros, añadiendo uno con prioridad 0 y otro con prioridad PHP_INT_MAX ? Pero aún necesitamos identificar la metaconsulta, así que supongo que necesitaríamos algo más con ese enfoque 😉 @PieterGoosen

    – birgire

    6 de julio de 2015 a las 9:44

  • Podría ser posible, sí, pero se complica bastante después de un tiempo. Intenté combinar algunos enfoques que no funcionaron. Como dije, su enfoque es definitivamente mejor y mucho menos complicado. La reutilización es genial aquí. Tiene una función simple, un parámetro adicional que reutiliza en cientos de consultas personalizadas sin tener que copiar y modificar sus filtros personalizados.

    – Pieter Goosen

    6 de julio de 2015 a las 9:45

  • sí, suena como un desafío más difícil ir por ese camino 😉 Solía ​​extender el WP_Query clase para cosas extra. Pero ahora prefiero simplemente agregar una nueva funcionalidad a través de parámetros personalizados, eso no romperá el código si se elimina el complemento y usando los prefijos wpse_ o solo _, en los nombres de parámetros personalizados, deberíamos poder evitar la colisión de nombres. Pero lo mejor de este enfoque es que también podemos usarlo en las consultas principales a través de pre_get_posts 😉 @PieterGoosen

    – birgire

    6 de julio de 2015 a las 9:53


  • Debo decir que me tienes enganchado a este enfoque 😉

    – Pieter Goosen

    6 de julio de 2015 a las 9:57

¿Ha sido útil esta solución?