Buscar solo entradas de blog en el widget de búsqueda de WordPress
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.

@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.

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

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

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

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 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 ;-)

Tu uso de pre_get_posts
es completamente incorrecto.
pre_get_posts
es una acción, no un filtro. Revisa el código fuentedo_action_ref_array( 'pre_get_posts', array( &$this ) );
Sí,
add_filter
funciona porqueadd_action
llama aadd_filter
, por eso tu código funcionará. Pero en cuanto al uso correcto, está simplemente mal. Si algo es una acción, usaadd_action()
. Simplemente tiene sentidoWP_Query::is_search
(yWP_Query::is_search()
para el caso) devuelve true en cualquier consulta donde se pases
aWP_Query
. Recuerda, las etiquetas condicionales dentro deWP_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 aWP_Query
vendrán de analizar la URL.pre_get_posts
altera todas las instancias deWP_Query
,query_posts
yget_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 usenget_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 …', '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;
}
}

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' );

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