César Aquino Maximiliano

Software Developer | Bombero Voluntario | Tech Instructor

Incluir custom field para las búsquedas de WordPress

Publicado el por César Aquino Maximiliano en la categoría Desarrollo web

El buscador de WordPress funciona muy bien cuando solo usamos los datos básicos de nuestra entrada. Pero cuando empezamos a jugar en serio con nuestro sitio y agregamos campos personalizados (más conocidos como custom fields) nos complica el hecho de que nuestras búsquedas lo incluyan.

Una búsqueda sencilla sería algo como esto:

$search = 'c';
$args = array(
        'post_type'     =>  'post',
        's'             =>  $search
);
$results = new WP_Query($args);
foreach ($results->posts as $post) {
        echo $post->post_title;
}
wp_reset_postdata();

Con esto, nos listará todas las entradas que tengan la letra «c» en el título, contenido o extracto.

Ahora, qué pasa cuando creamos un campo personalizado «fuente» para agregar la fuente de donde obtenemos nuestra entrada. Si queremos que al buscar también lo incluya en el resultado debemos hacer un poco de magia en nuestro código y lo incluiremos en la búsqueda.

Si han hecho algunas consultas en MySQL sabrán que necesitan hacer un INNER JOIN para que nuestra búsqueda incluya otra tabla. Asi que debemos agregar este codigo en nuestro archivo functions.php:

function add_join_search_field($joins) {
    global $wpdb;
    return $joins . " INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)";
}

Luego de agregar la tabla a la consulta SQL que hará WordPress debemos añadir un filtro más al WHERE:

function add_where_search_field($search,$qry) {
    global $wpdb;
    $add = $wpdb->prepare("({$wpdb->postmeta}.meta_key = 'fuente' AND CAST({$wpdb->postmeta}.meta_value AS CHAR) LIKE '%%%s%%')",$qry->get('s'));
    $pat = '|\(\((.+)\)\)|';
    $search = preg_replace($pat,'(($1 OR '.$add.'))',$search);
    return $search;
}

[ACTUALIZACIÓN 11/07/2016] Tuve un problema con mi búsqueda ya que al buscar por nombre y no por el custom field, me salían los resultados repetidas. Esto se debe a que en una consulta SQL de uno a muchos (tener conocimiento de BD) al hacer un join tienes que usar un GROUP BY para hacer que solo muestre los resultados sin repetirse. Para nuestra alegría, WordPress pensó en todo y nos dio un filter que nos ayudará con ello:

function add_groupby_search_field() {
    global $wpdb;
    $group = $wpdb->posts.'.ID';
    return $group;
}

Después de estas dos funciones ahora solo falta volver a hacer nuestro query para listar las entradas aunque con un poco de código adicional. Usaremos un add_filter para meternos a la consulta y agregar nuestro código. Luego de hacer la consulta removemos el filter:

$search = 'c';
$args = array(
        'post_type'     =>  'post',
        's'             =>  $search
);

add_filter('posts_join','add_join_search_field');
add_filter('posts_search','add_where_search_field',1,2);
add_filter( 'posts_groupby', 'add_groupby_search_field');
$results = new WP_Query($args);
remove_filter('posts_join','add_join_search_field');
remove_filter('posts_search','add_where_search_field',1,2);
remove_filter( 'posts_groupby', 'add_groupby_search_field');

foreach ($results->posts as $post) {
        echo $post->post_title;
}

wp_reset_postdata();

Listo! Con eso tendremos mejores resultados de búsqueda sin tener que depender de plugins. Si desconoces la función de los filters, puedes ver la diapositiva que realizó mi hermano para un meetup de la comunidad #WPPerú.

Etiquetas: