Buscar solo entradas de blog en el widget de búsqueda de WordPress

21 feb 2016, 22:23:17
Vistas: 18.3K
Votos: 4

Estaba usando este código:

add_filter( 'pre_get_posts','search_only_blog_posts' );

function search_only_blog_posts( $query ) {
    // Verifica si es una búsqueda y no está en el área de administración
    if ( $query->is_search && !is_admin() ) {
        // Establece que solo busque en posts normales
        $query->set( 'post_type', 'post' );
    }
    return $query;
}

...hasta que me di cuenta de que se aplicaba a casi cualquier búsqueda predeterminada en WordPress (incluyendo la búsqueda en la lista de posts del área de administración, etc.).

¿Cómo podría hacer que el widget de búsqueda solo busque en entradas de blog (no en posts personalizados, taxonomías, imágenes, etc.) sin que afecte otras búsquedas predeterminadas de WP (solo la del widget) ?

¿O sería más fácil crear mi propio widget de búsqueda?

Preferiría aprovechar todo lo que WordPress ofrece y no reinventar la rueda.

0
Todas las respuestas a la pregunta 5
6

@PieterGoosen tiene una buena explicación sobre por qué tu callback pre_get_posts te está causando problemas.

Aquí hay una solución alternativa para restringir el widget de búsqueda nativo al tipo de contenido post:

/**
 * Restringe los widgets de búsqueda nativos al tipo de contenido 'post'
 */
add_filter( 'widget_title', function( $title, $instance, $id_base )
{
    // Apuntamos a la base de búsqueda
    if( 'search' === $id_base )
        add_filter( 'get_search_form', 'wpse_post_type_restriction' );
    return $title;
}, 10, 3 );

function wpse_post_type_restriction( $html )
{
    // Solo se ejecuta una vez
    remove_filter( current_filter(), __FUNCTION__ );

    // Inyectamos el valor oculto post_type
    return str_replace( 
        '</form>', 
        '<input type="hidden" name="post_type" value="post" /></form>',
        $html 
    );
}

donde ajustamos la salida de la función get_search_form() pero solo para los widgets de búsqueda.

22 feb 2016 10:48:30
Comentarios

Un método bastante poco ortodoxo para usar el filtro widget_title ;-)

Pieter Goosen Pieter Goosen
22 feb 2016 10:59:26

sí, viene muy bien aquí, el filtro widget_display_callback era otra posibilidad ;-) @PieterGoosen

birgire birgire
22 feb 2016 11:12:33

Gracias por esa información, nunca se es demasiado viejo o feo para aprender algo nuevo ;-)

Pieter Goosen Pieter Goosen
22 feb 2016 11:15:01

Ambas son respuestas muy buenas pero tiendo a inclinarme por la más corta que utiliza la propia búsqueda de WordPress. @PieterGoosen, ¿no da WP_Widget un error de obsoleto? No he encontrado una alternativa en línea (hice solo unas búsquedas rápidas, no está en lo más alto de mi lista de prioridades ahora mismo).

N00b N00b
22 feb 2016 18:59:06

@N00b No, creo que lo confundes con los constructores de tipo PHP4 obsoletos. Como dije, mi código viene del núcleo mismo, solo cambié los nombres acordemente ;-)

Pieter Goosen Pieter Goosen
22 feb 2016 19:02:32

@PieterGoosen Ah, eso explica mucho, parece que no entendí completamente el error de obsoleto.. Gracias de todos modos. Puedo usar tu respuesta para arreglar mis widgets. ¡Dos pájaros de un tiro, bang!

N00b N00b
22 feb 2016 19:05:35
Mostrar los 1 comentarios restantes
1

Tu uso de pre_get_posts es completamente incorrecto.

  • pre_get_posts es una acción, no un filtro. Revisa el código fuente

    do_action_ref_array( 'pre_get_posts', array( &$this ) );
    

    Sí, add_filter funciona porque add_action llama a add_filter, por eso tu código funcionará. Pero en cuanto al uso correcto, está simplemente mal. Si algo es una acción, usa add_action(). Simplemente tiene sentido

  • WP_Query::is_search (y WP_Query::is_search() para el caso) devuelve true en cualquier consulta donde se pase s a WP_Query. Recuerda, las etiquetas condicionales dentro de WP_Query no se establecen según la URL, sino según las variables de consulta que se le pasan. Para la consulta principal, las variables de consulta pasadas a WP_Query vendrán de analizar la URL.

  • pre_get_posts altera todas las instancias de WP_Query, query_posts y get_posts, tanto en el front-end como en el back-end sin distinción, por lo que querrás apuntar solo a la consulta principal si solo deseas afectar la consulta principal. Además, solo querrás apuntar al front-end, especialmente para archivos y búsquedas.

Aquí hay un ejemplo de cómo usar pre_get_posts correctamente para la consulta principal: (Puedes cambiar el cierre a código normal si lo deseas, solo una nota, usa funciones anónimas solo si estás seguro de que no querrás eliminar la acción más tarde ya que no se pueden eliminar funciones anónimas)

add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin()         // Solo apunta al front-end,
         && $q->is_main_query() // Solo apunta a la consulta principal
         && $q->is_search()     // Solo apunta a la página de búsqueda
    ) {
        $q->set( 'post_type', ['my_custom_post_type', 'post'] );
    }
});

Para responder a tu pregunta sobre el widget de búsqueda, esto es lo que he encontrado

  • El widget de búsqueda simplemente llama a get_search_form()

  • No hay un filtro útil para apuntar específicamente al widget de búsqueda. Los filtros disponibles en get_search_form() afectarán a todos los formularios que usen get_search_form()

Con lo anterior, necesitarías crear tu propio widget de búsqueda con tu propio formulario personalizado

Puedes probar lo siguiente: (Modificado del widget de búsqueda del núcleo, nota, todo está sin probar)

class My_Custom_Search extends WP_Widget {
    /**
     * Configura una nueva instancia del widget de búsqueda.
     *
     * @since 1.0.0
     * @access public
     */
    public function __construct() {
        $widget_ops = [
            'classname'   => 'widget_custom_search', 
            'description' => __( "Un formulario de búsqueda personalizado para tu sitio.")
        ];
        parent::__construct( 'custom-search', _x( 'Búsqueda personalizada', 'Mi widget de búsqueda personalizado' ), $widget_ops );
    }

    /**
     * Muestra el contenido para la instancia actual del widget de búsqueda.
     *
     * @since 1.0.0
     * @access public
     *
     * @param array $args     Argumentos de visualización incluyendo 'before_title', 'after_title',
     *                        'before_widget', y 'after_widget'.
     * @param array $instance Configuración para la instancia actual del widget de búsqueda.
     */
    public function widget( $args, $instance ) {
        /** Este filtro está documentado en wp-includes/widgets/class-wp-widget-pages.php */
        $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
        echo $args['before_widget'];

        if ( $title ) {
            echo $args['before_title'] . $title . $args['after_title'];
        }

        $form = '<form role="search" method="get" class="search-form" action="' . esc_url( home_url( '/' ) ) . '">
            <label>
                <span class="screen-reader-text">' . _x( 'Buscar:', 'etiqueta' ) . '</span>
                <input type="search" class="search-field" placeholder="' . esc_attr_x( 'Buscar &hellip;', 'placeholder' ) . '" value="' . get_search_query() . '" name="s" title="' . esc_attr_x( 'Buscar:', 'etiqueta' ) . '" />
            </label>
            <input type="hidden" value="post" name="post_type" id="post_type" />
            <input type="submit" class="search-submit" value="'. esc_attr_x( 'Buscar', 'botón de enviar' ) .'" />
        </form>';

        echo $form;

        echo $args['after_widget'];
    }

    /**
     * Muestra el formulario de configuración para el widget de búsqueda.
     *
     * @since 1.0.0
     * @access public
     *
     * @param array $instance Configuración actual.
     */
    public function form( $instance ) {
        $instance = wp_parse_args( (array) $instance, ['title' => '')];
        $title = $instance['title'];
        ?>
        <p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Título:'); ?> <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>" /></label></p>
        <?php
    }

    /**
     * Maneja la actualización de la configuración para la instancia actual del widget de búsqueda.
     *
     * @since 1.0.0
     * @access public
     *
     * @param array $new_instance Nueva configuración para esta instancia ingresada por el usuario via
     *                            WP_Widget::form().
     * @param array $old_instance Configuración anterior para esta instancia.
     * @return array Configuración actualizada.
     */
    public function update( $new_instance, $old_instance ) {
        $instance = $old_instance;
        $new_instance = wp_parse_args((array) $new_instance, ['title' => '')];
        $instance['title'] = sanitize_text_field( $new_instance['title'] );
        return $instance;
    }
}
22 feb 2016 09:08:16
Comentarios

Por favor, consulta mi actualización

Pieter Goosen Pieter Goosen
22 feb 2016 10:21:33
1

Puedes simplemente colocar esto en tu archivo functions.php.

function SearchFilter($query) 
{
    if (($query->is_search)&&(!is_admin())) {
        $query->set('post_type', 'post');
    }
    return $query;
}

add_filter('pre_get_posts','SearchFilter');
12 abr 2016 15:53:09
Comentarios

¡Esto funcionó perfectamente - muy bien!

manifestor manifestor
19 sept 2018 17:43:32
1

Simplemente escribe este código en el functions.php de tu tema de WordPress.

function wpdocs_my_search_form( $form ) {
$form = '<form role="search" method="get" id="searchform" class="searchform" action="' . home_url( '/' ) . '" >
<div><label class="screen-reader-text" for="s">' . __( 'Buscar:' ) . '</label>
<input type="text" value="' . get_search_query() . '" name="s" id="s" />
<input type="hidden" value="post" name="post_type" id="post_type" />
<input type="submit" id="searchsubmit" value="'. esc_attr__( 'Buscar' ) .'" />
</div>
</form>';

return $form;
} add_filter( 'get_search_form', 'wpdocs_my_search_form' );
16 sept 2017 03:38:07
Comentarios

Por favor, explica por qué esto ayuda... en una edición. Gracias.

kaiser kaiser
16 sept 2017 12:22:12
2
-3

Por favor, consulta este código y configuración en el siguiente enlace

22 feb 2016 08:30:44
Comentarios

Por favor publica una respuesta real, no un enlace a alguna página donde alguien podría encontrar una solución

Pieter Goosen Pieter Goosen
22 feb 2016 08:54:27

Además esto es lo que el autor ya tiene, no le ayudará en nada...

flomei flomei
22 feb 2016 09:54:18