WordPress search: Customizar búsqueda para encontrar diferentes tipos de entradas

Hoy he tenido la necesidad de customizar la búsqueda por defecto de Worpdress, que usamos en la web corporativa de Paradigma, para poder mostrar en una misma página de resultados diferentes tipos de entradas/posts/artículos.

Aunque he visto que hay un par de plugins que hacen esta funcionalidad, he optado por adaptar la búsqueda por medio de funciones en el fichero functions.php de mi tema.

El primer problema es que para poder realizar estas búsquedas no podemos usar los campos por defecto de wordpress (por ejemplo el título o el contenido), así que necesitamos ejecutar una acción que añada un campo oculto por cada uno de los campos que necesitaremos para la búsqueda:

add_action( "save_post", "add_title_custom_field");

function add_title_custom_field($postid){
    // since we removed the "s" from the search query, we want to create
    // some custom fields for every post_title & post_content
    update_post_meta($postid, "_post_title", $_POST["post_title"]);
    update_post_meta($postid, "_post_content", $_POST["post_content"]);
}

Está acción se ejecutará cada vez que salvemos un post, y tendremos que tenerla siempre activa, para que todas las entradas que actualicemos tengan esta información. Pero ¿qué podemos hacer con todos las entradas que ya tenemos creadas en nuestro wordpress? ¿Es necesario salvar cada una por separado? Pues por suerte no. Con esta función que os pongo a continuación, y que basta con que sea ejecutada UNA ÚNICA VEZ, actualizaremos todo el contenido de nuestra base de datos, sin necesidad de tener que ir salvando uno a uno cada artículo.

// create new fields on every post of your wordpress
function addNewFieldsToPosts() {
    global $post;
    $args = array(
        'numberposts' => -1,
         //  set here each post type you want to search
        'post_type' => array( 'post', 'portfolio', 'openings', 'events' )
        );
    $the_query = get_posts( $args );
    if ($the_query) {
        foreach ($the_query as $post) {
            update_post_meta($post->ID, "_post_title", $post->post_title);
            update_post_meta($post->ID, "_post_content", $post->post_content);
        }
    }
}
wp_reset_query();
add_action('wp_head', 'addNewFieldsToPosts');

Si no ejecutamos estas dos funciones no encontraremos resultados en nuestras búsquedas.

Vale, si , muy bonito, pero… ¿Y la función necesaria para adaptar la búsqueda de WordPress? Pues aquí la teneis:

// CUSTOM SEARCH RESULTS
function custom_search_query( $query ) {
    $custom_fields = array(
        // put all the meta fields you want to search for here
        "_post_title", // we must add this fields on update_post_meta function
        "_post_content",
        "long_description"
    );
    $searchterm = $query->query_vars['s'];
    // we have to remove the "s" parameter from the query,
    // because it will prevent the posts from being found
    $query->query_vars['s'] = "";
    if ($searchterm != "") {
        //  set here each post type you want to search
        $query->set('post_type', array('post', 'pages', 'events', 'portfolio' ));
        $meta_query = array('relation' => 'OR');
        foreach($custom_fields as $cf) {
            array_push($meta_query, array(
                'key' => $cf,
                'value' => $searchterm,
                'compare' => 'LIKE'
            ));
        }
        $query->set("meta_query", $meta_query);
    };
}
add_filter( "pre_get_posts", "custom_search_query");

Diferenciar resultados por tipo de entrada

En nuestra página de resultados de búsqueda (search.php) podremos diferenciar cada resultado por su tipo de este modo:

$post_type = get_post_type( $post_id );

Espero que os sean de utilidad estas funciones. A mi me han salvado el día.