Incluir término de taxonomía personalizada en la búsqueda
Tengo dos taxonomías personalizadas aplicadas a dos tipos de contenido personalizados. Los términos se muestran correctamente en la barra lateral y listan todas las entradas asociadas. Sin embargo, si buscas uno de los términos específicamente, no muestra ninguna entrada con ese término.
Ejemplo: http://dev.andrewnorcross.com/das/all-case-studies/ Buscar el término "PQRI"
No obtengo ningún resultado. ¿Alguna idea? He intentado usar varios plugins de búsqueda pero o bien rompen mis parámetros de búsqueda personalizados o simplemente no funcionan.

También recomendaría el plugin Search Everything, pero si deseas implementar esto usando la función de búsqueda de WP, aquí está el código que uso en mi tema Atom:
// busca en todas las taxonomías, basado en: http://projects.jesseheap.com/all-projects/wordpress-plugin-tag-search-in-wordpress-23
function atom_search_where($where){
global $wpdb;
if (is_search())
$where .= "OR (t.name LIKE '%".get_search_query()."%' AND {$wpdb->posts}.post_status = 'publish')";
return $where;
}
function atom_search_join($join){
global $wpdb;
if (is_search())
$join .= "LEFT JOIN {$wpdb->term_relationships} tr ON {$wpdb->posts}.ID = tr.object_id INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id=tr.term_taxonomy_id INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id";
return $join;
}
function atom_search_groupby($groupby){
global $wpdb;
// necesitamos agrupar por ID de post
$groupby_id = "{$wpdb->posts}.ID";
if(!is_search() || strpos($groupby, $groupby_id) !== false) return $groupby;
// groupby estaba vacío, usa el nuestro
if(!strlen(trim($groupby))) return $groupby_id;
// no estaba vacío, añade el nuestro
return $groupby.", ".$groupby_id;
}
add_filter('posts_where','atom_search_where');
add_filter('posts_join', 'atom_search_join');
add_filter('posts_groupby', 'atom_search_groupby');
Está basado en el plugin Tag-Search: http://projects.jesseheap.com/all-projects/wordpress-plugin-tag-search-in-wordpress-23

Esto es genial, ¿cómo se puede modificar este código para excluir un array de IDs de taxonomía de la búsqueda?

Debe tenerse en cuenta que las funciones de callback para estos hooks aceptan 2 argumentos; el segundo para todos ellos siendo la instancia de WP_Query que se pasa por referencia. Cualquier verificación de is_search()
u otras llamadas a métodos de WP_Query (is_search()
, is_home()
, etc.) siempre deben llamarse directamente en la instancia de la consulta (por ejemplo, $query->is_search()
asumiendo que el nombre de la variable de instancia es $query
en la firma del callback) en lugar de la función de plantilla que siempre hará referencia a la consulta principal, no a la consulta para la que se está ejecutando el filtro.

Además, probablemente no sea una buena idea inyectar directamente la cadena de búsqueda disponible públicamente en una consulta SQL... lectura recomendada

Me gustaría añadir que esto tiene un conflicto con WPML porque WPML ya utiliza 'T' en la parte de unión, así que usar algo personalizado en lugar de tr, tt y t soluciona este problema

@EvanMattson — comentaste arriba que "probablemente no sea una buena idea inyectar la cadena de búsqueda pública directamente en una consulta SQL". ¿Cómo procederías para mitigar ese riesgo? Leí el enlace que proporcionaste pero no vi cómo se relaciona con la respuesta original. Muchas gracias, Em.

@TheChewy la respuesta anterior muestra get_search_query()
usado directamente en la sentencia MySQL de la cláusula WHERE. Este código es vulnerable a ataques de inyección SQL, donde cualquiera puede ejecutar consultas SQL arbitrarias en tu sitio pasándolas a través del campo de búsqueda. Obviamente así es como funcionan las búsquedas hasta cierto punto, pero lo importante es que esta entrada necesita ser preparada correctamente para asegurar que se interprete como términos de búsqueda y no como sentencias SQL. Para esto es el método $wpdb->prepare()
que se describe en la lectura recomendada

@TheChewy también puedes encontrar buenos ejemplos en la documentación de wpdb::prepare()
aquí: https://developer.wordpress.org/reference/classes/wpdb/prepare/

@EvanMattson Hola Evan, gracias por el aporte. Soy nuevo tanto en php como en código personalizado de WP y eso ha estado muy por encima de mi comprensión. ¿Serías capaz de duplicar el código con el $wpdb->prepare()
añadido si no es demasiado difícil? Creo que me llevará semanas llegar a entender ese tipo de cosas.

¿Es esta la búsqueda estándar de WordPress? Porque parece que no incluye taxonomías (ni siquiera las estándar, como categorías y etiquetas) en la búsqueda. El código busca en post_title
y post_content
, pero si quieres incluir algo más deberías engancharte al filtro posts_search
.

Probé la solución de Onetrickpony anteriormente mencionada https://wordpress.stackexchange.com/a/5404/37612, que es genial, pero encontré un problema que no funcionó para mí, y haría una pequeña modificación:
- si busqué una cadena en el título de la taxonomía - funciona perfectamente
si la taxonomía tiene caracteres especiales como las "Umlauts" alemanas (ö,ä,ü) y uno busca oe, ae, ue en lugar de usar el carácter especial - necesitas agregar la búsqueda en el slug de la taxonomía -
OR t.slug LIKE '%".get_search_query()."%'
si buscas una combinación de una consulta de búsqueda y un filtro de taxonomía - esto también funciona bien
Pero el problema es, cuando intentas usar solo el filtro de taxonomía - el hook de búsqueda añade una cadena vacía a la consulta si no se busca ningún texto, y por esa razón obtienes TODAS las publicaciones en el resultado, en lugar de solo aquellas de la taxonomía filtrada. Un simple IF resuelve el problema. Así que todo el código modificado sería este (¡funciona perfectamente bien para mí!)
function custom_search_where($where){ global $wpdb; if (is_search() && get_search_query()) $where .= "OR ((t.name LIKE '%".get_search_query()."%' OR t.slug LIKE '%".get_search_query()."%') AND {$wpdb->posts}.post_status = 'publish')"; return $where; } function custom_search_join($join){ global $wpdb; if (is_search()&& get_search_query()) $join .= "LEFT JOIN {$wpdb->term_relationships} tr ON {$wpdb->posts}.ID = tr.object_id INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id=tr.term_taxonomy_id INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id"; return $join; } function custom_search_groupby($groupby){ global $wpdb; // necesitamos agrupar por ID de publicación $groupby_id = "{$wpdb->posts}.ID"; if(!is_search() || strpos($groupby, $groupby_id) !== false || !get_search_query()) return $groupby; // groupby estaba vacío, usa el nuestro if(!strlen(trim($groupby))) return $groupby_id; // no estaba vacío, añade el nuestro return $groupby.", ".$groupby_id; } add_filter('posts_where','custom_search_where'); add_filter('posts_join', 'custom_search_join'); add_filter('posts_groupby', 'custom_search_groupby');

Encontré que la respuesta de onetrickpony era excelente, pero trata cualquier búsqueda como un solo término y no maneja frases de búsqueda entrecomilladas. Modifiqué su código (específicamente, la función atom_search_where
) un poco para manejar estas dos situaciones. Aquí está mi versión modificada de su código:
// Busca en todas las taxonomías, basado en: http://projects.jesseheap.com/all-projects/wordpress-plugin-tag-search-in-wordpress-23
function atom_search_where($where){
global $wpdb, $wp_query;
if (is_search()) {
$search_terms = get_query_var( 'search_terms' );
$where .= " OR (";
$i = 0;
foreach ($search_terms as $search_term) {
$i++;
if ($i>1) $where .= " AND"; // --- Cambia esto a OR si prefieres no requerir que todos los términos coincidan con las taxonomías
$where .= " (t.name LIKE '%".$search_term."%')";
}
$where .= " AND {$wpdb->posts}.post_status = 'publish')";
}
return $where;
}
function atom_search_join($join){
global $wpdb;
if (is_search())
$join .= "LEFT JOIN {$wpdb->term_relationships} tr ON {$wpdb->posts}.ID = tr.object_id INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id=tr.term_taxonomy_id INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id";
return $join;
}
function atom_search_groupby($groupby){
global $wpdb;
// Necesitamos agrupar por ID de post
$groupby_id = "{$wpdb->posts}.ID";
if(!is_search() || strpos($groupby, $groupby_id) !== false) return $groupby;
// groupby estaba vacío, usa el nuestro
if(!strlen(trim($groupby))) return $groupby_id;
// No estaba vacío, añade el nuestro
return $groupby.", ".$groupby_id;
}
add_filter('posts_where','atom_search_where');
add_filter('posts_join', 'atom_search_join');
add_filter('posts_groupby', 'atom_search_groupby');

Tengo el mismo nivel de información que Jan. Sé que también es posible ampliar la búsqueda con plugins.
Probablemente Search Everything (Plugin de WordPress) es lo que estás buscando. Según la lista de características, ahora soporta taxonomías personalizadas.

Tengo el mismo problema con el plugin de carrito WooCommerce... Mis resultados de búsqueda no incluyen el término de taxonomía personalizada 'product_tag', porque no es una etiqueta estándar de publicación. Encontré una solución en este otro hilo de StackOverflow sobre el tema:
El ejemplo de código de tkelly funcionó para mí cuando reemplacé el término author
en su ejemplo con product_tag
según nuestras necesidades para los plugins de carrito.
