web-dev-qa-db-fra.com

Comment créer une recherche de filtre avancée?

Ce n’est pas vraiment une question technique, mais c’est plutôt une introduction au sujet que je veux aborder.

C'est donc la première fois que je crée une page personnalisée de recherche avancée dans laquelle je dois recevoir des publications en fonction du type de publication personnalisé, des taxonomies personnalisées, des années et de l'ordre.

Le problème est que je ne sais vraiment pas comment jouer ici. Je cherchais des tutoriels ou des extraits sur Internet, mais tout ce que je trouve ne peut pas fonctionner avec les menus déroulants (pourquoi?, Je ne sais pas), tous les tutoriels que j'ai trouvés traitent de l'utilisation des cases à cocher.

Donc, toute recommandation ou code de fonction dont vous pouvez me parler?.

Merci d'avance.

Ceci est le code HTML que je veux utiliser:

<!-- Post Type -->
<div class="col-md-3">
    <div class="form-group">
        <label for="post_type">Post Type</label>
        <select class="form-control">
            <option>Any</option>
            <option>Post</option>
            <option>Portfolio</option>
            <option>Snippet</option>
        </select>
    </div>
</div>

<!-- Taxonomy -->
<div class="col-md-3">
    <div class="form-group">
        <label for="post_type">Taxonomy</label>
        <select class="form-control" multiple>
            <option>Any</option>
            <option>category</option>
            <option>portfolio_categories</option>
            <option>snippets_categories</option>
        </select>
    </div>
</div>

<!-- Year -->
<div class="col-md-3">
    <div class="form-group">
        <label for="post_type">Year</label>
        <select class="form-control">
            <option>Any</option>
            <option>2018</option>
            <option>2017</option>
            <option>2016</option>
            <option>2015</option>
            <option>2014</option>
        </select>
    </div>
</div>

<!-- Orderby -->
<div class="col-md-3">
    <div class="form-group">
        <label for="post_type">Order by</label>
        <select class="form-control" multiple>
            <option>Any</option>
            <option>Author</option>
            <option>Popularity (# of Comments)</option>
            <option>Views post_views_count</option>
            <option>Year</option>
            <option>ASC</option>
            <option>DESC</option>
        </select>
    </div>
</div>

<!-- Search Button -->
<div class="col-md-12">
    <input type="submit" class="btn btn-primary" id="buscar_btn" value="Search">
    <noscript>&lt;b&gt;Your browser does not support Javascript, this making it unable to display the posts.&lt;/b&gt;</noscript>
    <div id="resultados"><div class="cargando_medio"></div></div>
</div>

Voici la fonction du champ personnalisé post_view_count:

// Function to display number of views.
function getPostViews($postID){
    $count_key = 'post_views_count';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
        return "0 Views";
    }
    return $count.' Views';
}

// Function to count views.
function setPostViews($postID) {
    $count_key = 'post_views_count';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        $count = 0;
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
    }else{
        $count++;
        update_post_meta($postID, $count_key, $count);
    }
}


// Add it to a column in WP-Admin
function posts_column_views($defaults){
    $defaults['post_views'] = __('Views');
    return $defaults;
}
add_filter('manage_posts_columns', 'posts_column_views');
function posts_custom_column_views($column_name, $id){
    if($column_name === 'post_views'){
        echo getPostViews(get_the_ID());
    }
}
add_action('manage_posts_custom_column', 'posts_custom_column_views',5,2);

La fonction n'est pas vraiment bonne, en fait c'est pas bien mais ça fait le travail. Je vais peut-être devoir le changer plus tard, surtout parce que je veux qu'il compte les vues par adresse IP et par jour; il le fait actuellement en comptant les vues pour chaque REFRESH que je fais dans la page/publication en cours.

 enter image description here 

1
Kirasiris

Essaye ça:

PHP

add_action( 'wp_ajax_my_adv_search', 'ajax_my_adv_search' );
add_action( 'wp_ajax_nopriv_my_adv_search', 'ajax_my_adv_search' );
function ajax_my_adv_search() {
    if ( ! check_ajax_referer( 'my-adv-search', 'q_nonce', false ) ) {
        echo 'session_expired';
        wp_die();
    }

    $post_type = isset( $_POST['q_post_type'] ) ? $_POST['q_post_type'] : '';
    $taxonomy = isset( $_POST['q_taxonomy'] ) ? $_POST['q_taxonomy'] : [];
    $year = isset( $_POST['q_year'] ) ? $_POST['q_year'] : '';
    $orderby = isset( $_POST['q_orderby'] ) ? $_POST['q_orderby'] : [];
    $order = isset( $_POST['q_order'] ) ? $_POST['q_order'] : '';

    // Note that if $post_type is 'any', all post statuses will be included. In
    // that case, you may want to set specific post statuses below.
    $post_status = '';

    $taxonomy = array_filter( (array) $taxonomy );
    if ( ! in_array( 'any', $taxonomy ) ) {
        $taxonomy = array_unique( array_map( 'trim', $taxonomy ) );

        add_filter( 'posts_join', function( $c ) use ( $taxonomy ) {
            if ( ! empty( $taxonomy ) ) {
                global $wpdb;
                // 1 below is one/number and not the lowercase of L
                $c .= " INNER JOIN {$wpdb->term_relationships} AS ctr1 ON ctr1.object_id = {$wpdb->posts}.ID" .
                    " INNER JOIN {$wpdb->term_taxonomy} AS ctt1 ON ctt1.term_taxonomy_id = ctr1.term_taxonomy_id";
            }
            return $c;
        } );

        add_filter( 'posts_where', function( $c ) use ( $taxonomy ) {
            if ( ! empty( $taxonomy ) ) {
                $tax_list = array_map( 'esc_sql', $taxonomy );
                $tax_list = "'" . implode( "', '", $tax_list ) . "'";

                // 1 below is one/number and not the lowercase of L
                $c .= " AND ( ctt1.taxonomy IN ($tax_list) )";
            }
            return $c;
        } );
    }

    if ( ! is_numeric( $year ) ) {
        $year = '';
    }

    $orderby = array_filter( (array) $orderby );
    if ( in_array( 'any', $orderby ) ) {
        // Don't sort by post date.
        $orderby2 = false;
    } else {
        $orderby = array_unique( array_map( 'trim', $orderby ) );

        // TRUE if we're sorting by year.
        $ob_year = false;

        foreach ( $orderby as $i => $s ) {
            // Sort posts by year.
            if ( 'year' === $s ) {
                $ob_year = true;
                unset( $orderby[ $i ] );
            }

            // Sort posts by views count. Note that this would only return
            // posts that have the custom field 'post_views_count'.
            if ( 'views_count' === $s ) {
                $meta_key = 'post_views_count';
                $orderby2 = 'meta_value_num';
                unset( $orderby[ $i ] );
            }
        }

        add_filter( 'posts_orderby', function( $c, $q ) use ( $ob_year ) {
            if ( $ob_year ) {
                global $wpdb;

                // Use the value parsed by WP_Query.
                $order = $q->get( 'order' );

                $c .= $c ? ', ' : '';
                $c .= "YEAR({$wpdb->posts}.post_date) $order";
            }
            return $c;
        }, 10, 2 );

        $ok = isset( $orderby2 );
        if ( ! $ok && empty( $orderby ) ) {
            // Don't sort by post date.
            $orderby2 = false;
        } elseif ( ! $ok ) {
            // Pass to WP_Query as a string.
            $orderby2 = implode( ' ', $orderby );
        }
    }

    $q = new WP_Query( [
        'post_status' => $post_status,
        'post_type'   => $post_type,
        'year'        => $year,
        'meta_key'    => isset( $meta_key ) ? $meta_key : '',
        'orderby'     => $orderby2,
        'order'       => $order,
    ] );

    if ( $q->have_posts() ) {
        echo '<ul>';
        while ( $q->have_posts() ) {
            $q->the_post();

            echo '<li>';
                the_title(); echo '; ID: '; the_ID();
            echo '</li>';
        }
        echo '</ul>';
    } else {
        echo '<p>No posts found.</p>';
    }

    wp_die();
}

HTML

Examinez le "formulaire" ci-dessous et assurez-vous de définir le bon ID dans l'élément/menu select correspondant. Vous devez également ajouter les champs "commander" dans la colonne "Trier par" et le champ nonce avant le bouton d'envoi/de recherche.

<div id="my-adv-search">
<!-- Post Type -->
<div class="col-md-3">
    <div class="form-group">
        <label for="q_post_type">Post Type</label>
        <select class="form-control" id="q_post_type">
            <option value="any" selected>Any</option>
            ...
        </select>
    </div>
</div>

<!-- Taxonomy -->
<div class="col-md-3">
    <div class="form-group">
        <label for="q_taxonomy">Taxonomy</label>
        <select class="form-control" multiple id="q_taxonomy">
            <option value="any" selected>Any</option>
            ...
        </select>
    </div>
</div>

<!-- Year -->
<div class="col-md-3">
    <div class="form-group">
        <label for="q_year">Year</label>
        <select class="form-control" id="q_year">
            <option value="any" selected>Any</option>
            ...
        </select>
    </div>
</div>

<!-- Orderby -->
<div class="col-md-3">
    <div class="form-group">
        <label for="q_orderby">Order by</label>
        <select class="form-control" multiple id="q_orderby">
            <option value="any" selected>Any</option>
            <?php
            foreach ( [
              'author'        => 'Author',
              'comment_count' => 'Popularity (# of Comments)',
              'year'          => 'Year',
              'views_count'   => 'Views',
            ] as $value => $label ) {
              printf( '<option value="%s">%s</option>',
                esc_attr( $value ), esc_html( $label ) );
            }
            ?>
        </select>
    </div>
    <label class="radio-inline">
      <input type="radio" name="order" id="q_order-asc" value="ASC" />
      ASC
    </label>
    <label class="radio-inline">
      <input type="radio" name="order" id="q_order-desc" value="DESC" checked />
      DESC
    </label>
</div>

<!-- Nonce field. -->
<?php wp_nonce_field( 'my-adv-search', 'q_nonce' ); ?>

<!-- Search Button -->
<div class="col-md-12">
    <input type="submit" class="btn btn-primary" id="buscar_btn" value="Search">
    <noscript>&lt;b&gt;Your browser does not support Javascript, this making it unable to display the posts.&lt;/b&gt;</noscript>
    <div id="resultados"><div class="cargando_medio"></div></div>
</div>
</div><!-- End #my-adv-search -->

JS/jQuery/AJAX

Voir ci-dessous un exemple de script JS/jQuery qui effectue la recherche AJAX.

jQuery( function( $ ){
    var ajaxurl = '/path/to/wp-admin/admin-ajax.php';

    function searchPosts( btn ) {
        var _btn_text = btn.value,
            q_order;

        btn.disabled = true;
        btn.value = 'Searching..';

        q_order = $( '#q_order-asc' ).is( ':checked' ) ?
            'ASC' : 'DESC';

        return $.post( ajaxurl, {
            action: 'my_adv_search',
            q_nonce: $( '#q_nonce' ).val(),
            q_post_type: $( '#q_post_type' ).val(),
            q_taxonomy: $( '#q_taxonomy' ).val(),
            q_year: $( '#q_year' ).val(),
            q_orderby: $( '#q_orderby' ).val(),
            q_order: q_order,
        } ).done( function( s ){
            if ( 'session_expired' === s ) {
                location.reload();
                return;
            }

            $( '#resultados' ).html( s );
        } ).always( function(){
            btn.value = _btn_text;
            btn.disabled = false;
        } );
    }

    $( '#buscar_btn', '#my-adv-search' ).on( 'click', function( e ){
        e.preventDefault();

        // Run AJAX search.
        searchPosts( this );

        // Remove button focus.
        this.blur();
    } );
} );

Remarques

  • Dans la fonction ajax_my_adv_search() PHP, je n'ai pas utilisé tax_query avec l'appel WP_Query car nous interrogeons les publications qui se trouvent dans l'une des clés de taxonomie spécifiées (par exemple, category pour la catégorie standard Post et post_tags pour la catégorie standard balises), et pas dans un terme dans une taxonomie. Par conséquent, j’ai utilisé les crochets posts_join et posts_where dans WP_Query pour obtenir les résultats appropriés pour ce type de requête.

  • Dans la fonction ajax_my_adv_search() PHP, j'ai également utilisé le hook posts_orderby dans WP_Query car sorting posts/results par année n'est pas disponible par défaut dans la classe WP_Query.

3
Sally CJ