Cum să limitezi căutarea WordPress doar la articolele de blog (widget-ul implicit)
Am folosit acest cod:
add_filter( 'pre_get_posts','search_only_blog_posts' );
function search_only_blog_posts( $query ) {
if ( $query->is_search ) {
$query->set( 'post_type', 'post' );
}
return $query;
}
...până când am realizat că se aplică la aproape orice căutare implicită din WordPress (inclusiv căutarea în lista de articole din zona de administrare etc.).
Cum aș putea face ca widget-ul de căutare să caute doar articolele de blog (nu postări personalizate, taxonomii, imagini etc.) fără să afecteze alte căutări implicite din WP (doar căutarea prin widget) ?
Sau este mai ușor să creez propriul meu widget de căutare?
Aș prefera să utilizez tot ceea ce oferă WordPress și să nu reinventez roata.

@PieterGoosen are o descriere bună despre motivul pentru care funcția ta de callback pre_get_posts
îți creează probleme.
Iată o soluție alternativă pentru a restricționa widget-ul nativ de căutare doar la tipul de postare post:
/**
* Restricționează widget-urile native de căutare la tipul de postare 'post'
*/
add_filter( 'widget_title', function( $title, $instance, $id_base )
{
// Țintim baza de căutare
if( 'search' === $id_base )
add_filter( 'get_search_form', 'wpse_post_type_restriction' );
return $title;
}, 10, 3 );
function wpse_post_type_restriction( $html )
{
// Rulează doar o singură dată
remove_filter( current_filter(), __FUNCTION__ );
// Adaugă valoarea ascunsă pentru post_type
return str_replace(
'</form>',
'<input type="hidden" name="post_type" value="post" /></form>',
$html
);
}
unde ajustăm rezultatul funcției get_search_form()
dar numai pentru widget-urile de căutare.

O metodă destul de neortodoxă de a folosi filtrul widget_title
;-)

da, este util aici, filtrul widget_display_callback
era o altă posibilitate ;-) @PieterGoosen

Mulțumesc pentru informație, nu ești niciodată prea bătrân sau prea urât pentru a învăța ceva nou ;-)

Ambele sunt răspunsuri foarte bune, dar tind să optez pentru cel mai scurt care utilizează chiar căutarea WordPress. @PieterGoosen, nu dă WP_Widget
o eroare de depreciere? Nu am găsit o alternativă online (am făcut doar câteva căutări rapide, nu e în topul priorităților mele acum).

@N00b Nu, cred că îl confunzi cu constructorii deprecieri de tip PHP4. Cum am spus, codul meu vine din nucleul însuși, doar am schimbat numele în consecință ;-)

Utilizarea ta a lui pre_get_posts
este complet greșită.
pre_get_posts
este o acțiune, nu un filtru. Verifică sursado_action_ref_array( 'pre_get_posts', array( &$this ) );
Da,
add_filter
funcționează deoareceadd_action
apeleazăadd_filter
, de aceea codul tău va funcționa. Dar în ceea ce privește utilizarea corectă, este pur și simplu greșit. Dacă ceva este o acțiune, foloseșteadd_action()
. Are logicăWP_Query::is_search
(șiWP_Query::is_search()
de altfel) returnează true pentru orice interogare undes
este transmis cătreWP_Query
. Ține minte, condiționalele din interiorulWP_Query
nu sunt setate în funcție de URL, ci în funcție de variabilele de interogare transmise acestuia. Pentru interogarea principală, variabilele de interogare transmise cătreWP_Query
vor veni din parsarea URL-ului.pre_get_posts
modifică toate instanțele deWP_Query
,query_posts
șiget_posts
, atât în front-end cât și în back-end, indiferent, deci vei dori să țintești doar interogarea principală dacă dorești să afectezi doar aceasta. În plus, vei dori să țintești doar front-end-ul, în special pentru arhive și interogări de căutare.
Iată un exemplu despre cum să utilizezi pre_get_posts
corect pentru interogarea principală: (Poți schimba closure-ul în spaghetti normal dacă dorești, doar o notă, folosește funcții anonime doar dacă ești sigur că nu vei dori să elimini acțiunea mai târziu deoarece funcțiile anonime nu pot fi eliminate)
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Doar în front-end,
&& $q->is_main_query() // Doar interogarea principală
&& $q->is_search() // Doar pagina de căutare
) {
$q->set( 'post_type', ['my_custom_post_type', 'post'] );
}
});
Pentru a răspunde la întrebarea ta despre widget-ul de căutare, iată ce am descoperit
Widget-ul de căutare apelează simplu
get_search_form()
Nu există niciun filtru util pentru a ținti specific widget-ul de căutare. Filtrele disponibile în
get_search_form()
vor afecta toate formularele care folosescget_search_form()
Cu cele de mai sus, va trebui să creezi propriul widget de căutare cu propriul formular personalizat
Poți încerca următoarele: (Modificat din widget-ul de căutare din nucleu, atenție, nimic nu este testat)
class My_Custom_Search extends WP_Widget {
/**
* Inițializează o nouă instanță a widget-ului de căutare.
*
* @since 1.0.0
* @access public
*/
public function __construct() {
$widget_ops = [
'classname' => 'widget_custom_search',
'description' => __( "Un formular de căutare personalizat pentru site-ul tău.")
];
parent::__construct( 'custom-search', _x( 'Căutare personalizată', 'Widget-ul meu de căutare personalizat' ), $widget_ops );
}
/**
* Afișează conținutul pentru instanța curentă a widget-ului de căutare.
*
* @since 1.0.0
* @access public
*
* @param array $args Argumente de afișare incluzând 'before_title', 'after_title',
* 'before_widget', și 'after_widget'.
* @param array $instance Setări pentru instanța curentă a widget-ului de căutare.
*/
public function widget( $args, $instance ) {
/** Acest filtru este documentat în 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( 'Caută:', 'etichetă' ) . '</span>
<input type="search" class="search-field" placeholder="' . esc_attr_x( 'Caută …', 'placeholder' ) . '" value="' . get_search_query() . '" name="s" title="' . esc_attr_x( 'Caută:', 'etichetă' ) . '" />
</label>
<input type="hidden" value="post" name="post_type" id="post_type" />
<input type="submit" class="search-submit" value="'. esc_attr_x( 'Caută', 'buton trimitere' ) .'" />
</form>';
echo $form;
echo $args['after_widget'];
}
/**
* Afișează formularul de setări pentru widget-ul de căutare.
*
* @since 1.0.0
* @access public
*
* @param array $instance Setări curente.
*/
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('Titlu:'); ?> <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
}
/**
* Gestionează actualizarea setărilor pentru instanța curentă a widget-ului de căutare.
*
* @since 1.0.0
* @access public
*
* @param array $new_instance Noile setări pentru această instanță introduse de utilizator prin
* WP_Widget::form().
* @param array $old_instance Vechile setări pentru această instanță.
* @return array Setări actualizate.
*/
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;
}
}

Pur și simplu adaugă acest cod în fișierul functions.php al temei tale 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">' . __( 'Caută:' ) . '</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__( 'Caută' ) .'" />
</div>
</form>';
return $form;
} add_filter( 'get_search_form', 'wpdocs_my_search_form' );

Vă rugăm să consultați acest cod și setarea următorul link
