Cum să limitezi căutarea WordPress doar la articolele de blog (widget-ul implicit)

21 feb. 2016, 22:23:17
Vizualizări: 18.3K
Voturi: 4

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.

0
Toate răspunsurile la întrebare 5
6

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

22 feb. 2016 10:48:30
Comentarii

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

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

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

birgire birgire
22 feb. 2016 11:12:33

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

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

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 N00b
22 feb. 2016 18:59:06

@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ță ;-)

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

@PieterGoosen Ah, asta explică multe, se pare că nu am înțeles pe deplin eroarea de depreciere.. Oricum, mulțumesc. Pot folosi răspunsul tău pentru a-mi repara widget-urile. Doi iepuri dintr-o lovitură, bang!

N00b N00b
22 feb. 2016 19:05:35
Arată celelalte 1 comentarii
1

Utilizarea ta a lui pre_get_posts este complet greșită.

  • pre_get_posts este o acțiune, nu un filtru. Verifică sursa

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

    Da, add_filter funcționează deoarece add_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ște add_action(). Are logică

  • WP_Query::is_search (și WP_Query::is_search() de altfel) returnează true pentru orice interogare unde s este transmis către WP_Query. Ține minte, condiționalele din interiorul WP_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ătre WP_Query vor veni din parsarea URL-ului.

  • pre_get_posts modifică toate instanțele de WP_Query, query_posts și get_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 folosesc get_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ă &hellip;', '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;
    }
}
22 feb. 2016 09:08:16
Comentarii

Vă rugăm să vedeți actualizarea mea

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

Puteți adăuga pur și simplu acest cod în fișierul 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 apr. 2016 15:53:09
Comentarii

A funcționat perfect - foarte frumos!

manifestor manifestor
19 sept. 2018 17:43:32
1

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' );
16 sept. 2017 03:38:07
Comentarii

Te rog să explici de ce acest lucru ajută... într-o editare. Mulțumesc.

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

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

22 feb. 2016 08:30:44
Comentarii

Te rog postează un răspuns real, nu un link către o pagină unde poate cineva să găsească o soluție

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

Mai mult, asta este ceea ce autorul deja are, nu-l va ajuta cu nimic...

flomei flomei
22 feb. 2016 09:54:18