Variables de consulta personalizadas JetSmartFilters — ¿Necesitas filtrar contenido en WordPress con criterios que JetSmartFilters no soporta por defecto? Imagina que tienes experiencias de viaje (posts) y quieres filtrarlas por el NIT o razón social de los usuarios relacionados. Suena complejo, pero con variables de consulta personalizadas para JetSmartFilters es posible. Te explico paso a paso cómo lograrlo.
¿Por qué necesitas variables de consulta personalizadas?
JetSmartFilters es excelente para filtros básicos, pero cuando necesitas cruzar datos entre diferentes entidades (como posts y metadatos de usuarios), el plugin solo te muestra la puerta. Tú debes abrirla con código personalizado. Es como querer buscar restaurantes por el nombre del chef: necesitas conectar dos tablas de información.
Lo que vas a lograr
- Filtrar experiencias (posts) por metacampos de usuarios relacionados
- Entender el flujo de consultas de JetSmartFilters
- Evitar el error que bloquea todos los resultados
- Optimizar el rendimiento de tus filtros personalizados
Preparación: lo que necesitas antes de empezar
Antes de meter las manos en el código, asegúrate de tener:
- WordPress 5.0 o superior (lo más probable es que ya lo tengas)
- JetEngine y JetSmartFilters instalados y activados
- Acceso al archivo functions.php de tu tema o mejor, un plugin personalizado
- Conocimientos básicos de PHP (no necesitas ser experto)
Entendiendo el problema principal
Aquí está el truco: JetSmartFilters por defecto agrega términos de búsqueda al meta_query. Si el metaclave no existe en tus posts, WordPress dice «aquí no hay nada» y bloquea TODOS los resultados, incluso si tú manualmente le dices qué posts mostrar. Es como si un guardia de seguridad demasiado estricto no te dejara entrar a tu propia fiesta.
Ejemplo práctico: filtrar experiencias por datos de usuarios
Vamos con un caso real que me encontré en un proyecto:
- Tipo de post: Experiencias de viaje (
rp_us_experiences) - Relación: Usuarios → Experiencias (vía JetEngine, ID 11)
- Campos a buscar: NIT de empresa (
rp_us_nit) y razón social (rp_us_company_reason) del usuario - Objetivo: Cuando alguien busque «123456» o «Mi Empresa SAS», ver las experiencias de ese usuario
Paso 1: Crear la clase personalizada
Crea un archivo en tu plugin: wp-content/plugins/tu-plugin/includes/class-custom-jetsmartfilters.php
<?php
/**
* Manejador personalizado para JetSmartFilters
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Custom_JetSmartFilters {
public function __construct() {
// Conectarnos al filtro final de JetSmartFilters
add_filter( 'jet-smart-filters/query/final-query', array( $this, 'filter_by_related_meta' ), 10, 1 );
}
public function filter_by_related_meta( $query ) {
global $wpdb;
// Solo aplicar a nuestro listing específico
if ( empty( $query['jet_smart_filters'] ) ||
false === strpos( $query['jet_smart_filters'], 'experiences' ) ) {
return $query;
}
// Extraer el término de búsqueda
$search_term = $this->get_search_term( $query );
if ( empty( $search_term ) ) {
return $query;
}
// Obtener IDs de posts filtrados
$filtered_ids = $this->get_filtered_post_ids( $search_term );
if ( empty( $filtered_ids ) ) {
$query['post__in'] = array( 0 );
return $query;
}
// Aplicar post__in
$query['post__in'] = $this->merge_post_in( $query, $filtered_ids );
// CRÍTICO: Remover meta_query de plain_query para evitar bloqueo
$query = $this->remove_plain_query_meta( $query );
return $query;
}
private function get_search_term( $query ) {
$search_term = '';
// Método 1: Desde meta_query
if ( ! empty( $query['meta_query'] ) ) {
foreach ( $query['meta_query'] as $meta ) {
if ( isset( $meta['key'], $meta['value'] ) &&
'plain_query' === $meta['key'] ) {
$search_term = sanitize_text_field( $meta['value'] );
break;
}
}
}
// Método 2: Desde $_REQUEST (respaldo)
if ( empty( $search_term ) &&
isset( $_REQUEST['_plain_query|custom_filter'] ) ) {
$search_term = sanitize_text_field(
wp_unslash( $_REQUEST['_plain_query|custom_filter'] )
);
}
return $search_term;
}
private function get_filtered_post_ids( $search_term ) {
global $wpdb;
$like = '%' . $wpdb->esc_like( $search_term ) . '%';
$relation_table = $wpdb->prefix . 'jet_rel_default';
// Verificar que la tabla existe
if ( $wpdb->get_var( $wpdb->prepare(
'SHOW TABLES LIKE %s',
$relation_table
) ) !== $relation_table ) {
return array();
}
// Consulta SQL personalizada
$post_ids = $wpdb->get_col( $wpdb->prepare(
"SELECT DISTINCT rel.child_object_id
FROM {$relation_table} rel
LEFT JOIN {$wpdb->usermeta} um1
ON um1.user_id = rel.parent_object_id
AND um1.meta_key = 'rp_us_company_reason'
LEFT JOIN {$wpdb->usermeta} um2
ON um2.user_id = rel.parent_object_id
AND um2.meta_key = 'rp_us_nit'
WHERE rel.child_object_id IS NOT NULL
AND ( um1.meta_value LIKE %s OR um2.meta_value LIKE %s )
GROUP BY rel.child_object_id",
$like,
$like
) );
return $post_ids;
}
private function merge_post_in( $query, $filtered_ids ) {
if ( ! empty( $query['post__in'] ) ) {
$merged = array_intersect( $query['post__in'], $filtered_ids );
return ! empty( $merged ) ? $merged : array( 0 );
}
return $filtered_ids;
}
private function remove_plain_query_meta( $query ) {
if ( ! empty( $query['meta_query'] ) ) {
$query['meta_query'] = array_values( array_filter(
$query['meta_query'],
function( $row ) {
return empty( $row['key'] ) || 'plain_query' !== $row['key'];
}
) );
if ( empty( $query['meta_query'] ) ) {
unset( $query['meta_query'] );
}
}
return $query;
}
}
// Inicializar
new Custom_JetSmartFilters();
Paso 2: Configurar JetSmartFilters
- Ve a JetSmartFilters → Añadir nuevo
- Elige tipo «Búsqueda»
- Configura Variable de consulta:
plain_query|custom_filter - Aplica a tu listing provider
- Guarda el filtro
Paso 3: Añadir filtro a tu listing
- Edita tu JetEngine Listing Grid
- Añade el widget JetSmartFilters
- Selecciona tu filtro personalizado
- Guarda y prueba
Problemas comunes y soluciones
Problema 1: El filtro no muestra resultados
Síntoma: La búsqueda siempre devuelve «No se encontraron resultados».
Causa: El meta_query con plain_query está bloqueando todo.
Solución: Siempre remueve el plain_query después de extraer el término de búsqueda. Esa función remove_plain_query_meta() en el código es tu mejor amiga.
Problema 2: El hook no se ejecuta
Síntoma: Tu código no hace nada, ni siquiera errores.
Verifica:
- El archivo está incluido en tu tema/plugin
- La clase se instancia (esa línea
new Custom_JetSmartFilters()al final) - El número de argumentos en
add_filter()es 1
Problema 3: Filtro aplicado al listing equivocado
Síntoma: El filtro funciona, pero en todos los listings del sitio.
Solución: Ajusta la condición en tu función:
// Cambia 'experiences' por el ID de tu listing
if ( false === strpos( $query['jet_smart_filters'], 'tu-listing-id' ) ) {
return $query;
}
Optimización de rendimiento
1. Agrega índices a la base de datos
Para miles de registros, un índice acelera la búsqueda como ponerle turbo a un carro:
CREATE INDEX idx_meta_search
ON wp_usermeta(meta_key, meta_value(50))
WHERE meta_key IN ('rp_us_nit', 'rp_us_company_reason');
2. Implementa caché
Si los mismos términos se buscan frecuentemente, guarda los resultados:
private function get_filtered_post_ids( $search_term ) {
$cache_key = 'custom_filter_' . md5( $search_term );
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
// Tu consulta SQL aquí...
// Guardar por 1 hora
set_transient( $cache_key, $post_ids, HOUR_IN_SECONDS );
return $post_ids;
}
3. Limita los resultados
Para no sobrecargar la base de datos:
SELECT DISTINCT rel.child_object_id
FROM {$relation_table} rel
-- ... tus joins ...
GROUP BY rel.child_object_id
LIMIT 100 // ← Esto es importante
Técnicas avanzadas
Múltiples campos de búsqueda
¿Necesitas buscar en más de dos campos? Solo añade más LEFT JOINs:
LEFT JOIN {$wpdb->usermeta} um3
ON um3.user_id = rel.parent_object_id
AND um3.meta_key = 'otro_campo'
Y en el WHERE: OR um3.meta_value LIKE %s
Combinar con taxonomías
¿Quieres filtrar también por categorías o etiquetas? Usa wp_terms y wp_term_relationships en tu consulta.
Buenas prácticas que te ahorrarán dolores de cabeza
- Siempre sanitiza: Usa
sanitize_text_field()como en el ejemplo - Prepared statements: Nunca concatenes variables directamente en SQL
- Verifica tablas: Comprueba que las tablas existen antes de consultarlas
- Debug estratégico: Usa
error_log()solo en desarrollo - Respeta filtros existentes: Usa
array_intersect()para no pisar otros filtros
Conclusión
Crear variables de consulta personalizadas para JetSmartFilters es como aprender a conducir manual después de solo usar automático: al principio parece complicado, pero una vez lo dominas, tienes mucho más control.
Los puntos clave que debes recordar:
- El hook
jet-smart-filters/query/final-queryes tu punto de entrada - Extrae el término de búsqueda del
meta_queryo$_REQUEST - SIEMPRE remueve el
plain_querydelmeta_querydespués - Optimiza con índices y caché para sitios con muchos datos
- Prueba tus consultas SQL directamente en phpMyAdmin primero
¿Tienes dudas específicas sobre tu implementación? En la comunidad de Crocoblock hay desarrolladores que pueden ayudarte. Y si quieres profundizar en desarrollo WordPress, la documentación oficial es tu mejor aliada.
¿Qué tipo de filtros personalizados necesitas crear? Cuéntame en los comentarios y veamos cómo solucionarlo juntos.