【问题标题】:Wordpress - Multi Taxonomy Ajax Filter with Ajax load more PostsWordpress - 使用 Ajax 加载更多帖子的多分类 Ajax 过滤器
【发布时间】:2019-03-18 09:47:10
【问题描述】:

经过一个月的尝试终于可以正常工作了,但是有一个小问题我想不通!如果他发现两个分类之间的帖子,过滤器就可以了,但如果没有任何帖子,它应该给我get_template_part( 'template-parts/content', 'none' );,但他停止了过滤......!

这是模板页面。

<?php
/**
 * Template Name: Cat Filter Full Width
 *
 * Use this template to build pages with Page Builders.
 * 
 * @package HitMag
 */

get_header(); ?>

<div class="filter-content-area" style="position: relative;">
    <div id="primary-filter">
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="misha_filters">

<?php echo "<label><input type='checkbox' name='all'> All</label>"; ?>

    <?php

        if( $terms = get_terms( 'zones', 'orderby=name%parent=0' ) ) : // to make it simple I use default categories
            echo '<select name="categoryfilter"><option>All Creative Zones...</option>';
            foreach ( $terms as $term ) :
                echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // ID of the category as the value of an option
            endforeach;
            echo '</select>';
        endif;
    ?>
    <?php

        if( $terms = get_terms( 'category', 'orderby=name%parent=0&exclude=233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,18,212,214,47,35,125,6,17,209,252' ) ) : // to make it simple I use default categories
            echo '<select name="categoryfilter2"><option>Select Zone...</option>';
            foreach ( $terms as $term ) :
                echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // ID of the category as the value of an option
            endforeach;
            echo '</select>';
        endif;
    ?>
    <button>Apply filter</button>
    <input type="hidden" name="action" value="myfilter">

</form>
    </div>
</div>
        <?php


$args = array(
    'orderby' => 'date',
    'post_type' => 'post',
    'post_status' => 'publish',
    'ignore_sticky_posts' => 1,
    'posts_per_page' => 18,
    'tax_query' => array(
        array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => array('galleries')
        ),
    )
);

$query = new WP_Query( $args );

        if ( $query->have_posts() ) : ?>
                <div id="responses">
            <?php

            $archive_content_layout = get_option( 'archive_content_layout', 'th-grid-2' );
            echo '<div class="posts-wrap ' . esc_attr( $archive_content_layout ) . '">';

                /* Start the Loop */
                while ( $query->have_posts() ) : $query->the_post();

                    get_template_part( 'template-parts/content', get_post_format() );

                endwhile;

            echo '</div><!-- .posts-wrap -->';
        wp_reset_postdata();
?>
</div>
<?php 
global $wp_query;

if (  $query->max_num_pages > 1 ) :
    echo '<div id="misha_loadmore">More posts</div>'; // you can use <a> as well
endif;
            the_posts_pagination();

        else :

            get_template_part( 'template-parts/content', 'none' );

        endif; ?>

        </main><!-- #main -->
    </div><!-- #primary -->

<?php
get_sidebar();
get_footer();

我的 loadmore 脚本的 Js

function misha_my_load_more_button_scripts() {

    global $wp_query; 

    wp_register_script( 'misha_filter_scripts', get_stylesheet_directory_uri().'/custom-js/myloadmorebutton.js', array('jquery'), '1.0.0', true );
    wp_enqueue_script( 'misha_filter_scripts' );

    // now the most interesting part
    // we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP
    // you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script()
    wp_localize_script( 'misha_filter_scripts', 'misha_loadmore_button_params', array(
        'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
        'posts' => json_encode( $query->query_vars ), // everything about your loop is here
        'current_page' => $query->query_vars['paged'] ? $query->query_vars['paged'] : 1,
        'max_page' => $query->max_num_pages
    ) );
}

add_action( 'wp_enqueue_scripts', 'misha_my_load_more_button_scripts', 1 );

这就是过滤功能。

function misha_filter_function(){

    $args = array(
        'post_type' => 'post',
        'post_status' => 'publish',
        'ignore_sticky_posts' => 1,
        'posts_per_page' => '18'
    );

        $args['tax_query'] = array(
            'relation' => 'AND',
        );

if( empty( $_POST['all'] ) ) {
    if( isset( $_POST['categoryfilter'] ) )
            $args['tax_query'] = array(
                array(
                    'taxonomy' => 'zones',
                    'field' => 'id',
                    'terms' => $_POST['categoryfilter'],
                )
            );

if( isset( $_POST['categoryfilter'] ) )
    $args['tax_query'][] = array(
        array(
            'taxonomy' => 'zones',
            'field' => 'id',
            'terms' => $_POST['categoryfilter'],
        )
    );


if( isset( $_POST['categoryfilter2'] ) )
    $args['tax_query'][] = array(
        array(
            'taxonomy' => 'category',
            'field' => 'id',
            'terms' => $_POST['categoryfilter2'],
        )
    );
} 

    $query = new WP_Query( $args );

global $wp_query;

    if( $query->have_posts() ) :

        ob_start(); 

            $archive_content_layout = get_option( 'archive_content_layout', 'th-grid-2' );
            echo '<div class="posts-wrap ' . esc_attr( $archive_content_layout ) . '">';

        while( $query->have_posts() ): $query->the_post();

            get_template_part( 'template-parts/content', get_post_format() );


        endwhile;

            echo '</div><!-- .posts-wrap -->';
        wp_reset_postdata();
        $content = ob_get_contents(); // we pass the posts to variable
        ob_end_clean(); // clear the buffer

    else :
        get_template_part( 'template-parts/content', 'none' );
    endif;

    echo json_encode( array(
        'posts' => serialize( $query->query_vars ),
        'max_page' => $query->max_num_pages,
        'found_posts' => $query->found_posts,
        'content' => $content
    ) );

    die();
}
add_action('wp_ajax_myfilter', 'misha_filter_function'); 
add_action('wp_ajax_nopriv_myfilter', 'misha_filter_function');

而且这个功能适用于 Ajax 加载更多帖子。

add_action('wp_ajax_loadmorebutton', 'misha_loadmore_button_ajax_handler');
add_action('wp_ajax_nopriv_loadmorebutton', 'misha_loadmore_button_ajax_handler');

function misha_loadmore_button_ajax_handler(){

    $args = unserialize( stripslashes( $_POST['query']) );
    $args['paged'] = $_POST['page'] + 1; 
    $args['post_status'] = 'publish';

$query = new WP_Query( $args );

    global $wp_query;

    if( $query->have_posts() ) :

            $archive_content_layout = get_option( 'archive_content_layout', 'th-grid-2' );
            echo '<div class="posts-wrap ' . esc_attr( $archive_content_layout ) . '">';

        while( $query->have_posts() ): $query->the_post();

            get_template_part( 'template-parts/content', get_post_format() );


        endwhile;

            echo '</div><!-- .posts-wrap -->';


    else :
        get_template_part( 'template-parts/content', 'none' );
    endif;

    die; 
}

最后还有 JS 用于过滤功能 action 和 loadmore。

jQuery(document).ready( function($) {

    /*
     * Load More
     */
    $('#misha_loadmore').click(function(){

        $.ajax({
            url : misha_loadmore_button_params.ajaxurl, // AJAX handler
            data : {
                'action': 'loadmorebutton', // the parameter for admin-ajax.php
                'query': misha_loadmore_button_params.posts, // loop parameters passed by wp_localize_script()
                'page' : misha_loadmore_button_params.current_page // current page
            },
            type : 'POST',
            beforeSend : function ( xhr ) {
                $('#misha_loadmore').text('Loading...'); // some type of preloader
            },
            success : function( data ){
                if( data ) {

                    $('#misha_loadmore').text( 'More posts' );
                    $('#responses').append(data); // insert new posts
                    misha_loadmore_button_params.current_page++;

                    if ( misha_loadmore_button_params.current_page == misha_loadmore_button_params.max_page ) 
                        $('#misha_loadmore').hide(); // if last page, HIDE the button

                } else {
                    $('#misha_loadmore').hide(); // if no data, HIDE the button as well
                }
            }
        });
        return false;
    });

    /*
     * Filter
     */
    $('#misha_filters').submit(function(){

        $.ajax({
            url : misha_loadmore_button_params.ajaxurl,
            data : $('#misha_filters').serialize(), // form data
            dataType : 'json', // this data type allows us to receive objects from the server
            type : 'POST',
            beforeSend : function(xhr){
                $('#misha_filters').find('button').text('Filtering...');
            },
            success:function(data){

                $('html,body').animate({ scrollTop: $("#main").offset().top }, "slow");

                // when filter applied:
                // set the current page to 1
                misha_loadmore_button_params.current_page = 1;

                // set the new query parameters
                misha_loadmore_button_params.posts = data.posts;

                // set the new max page parameter
                misha_loadmore_button_params.max_page = data.max_page;

                // change the button label back
                $('#misha_filters').find('button').text('Apply filter');

                // insert the posts to the container
                $('#responses').html(data.content);

                // hide load more button, if there are not enough posts for the second page
                if ( data.max_page < 2 ) {
                    $('#misha_loadmore').hide();
                } else {
                    $('#misha_loadmore').show();
                }
            }
        });

        // do not submit the form
        return false;

    });

});

【问题讨论】:

    标签: php ajax wordpress filter taxonomy


    【解决方案1】:

    由于您要将模板的输出分配给变量$content,因此您需要在过滤器函数的 else 分支中使用输出缓冲;就像您在 if 分支中所做的那样。 else 部分将如下所示:

    else :
        ob_start(); // start the buffer to capture the output of the template
        get_template_part( 'template-parts/content', 'none' );
        $content = ob_get_contents(); // pass the output to variable
        ob_end_clean(); // clear the buffer
    

    与您当前的问题无关的小警告。你不应该像你那样使用unserialize。这是非常不安全的。 manual 中有一个红色警告,您可以通过搜索 PHP 对象注入轻松找到其危险性的解释。

    帮自己一个忙,使用json_encode/decode。应该没什么区别,因为 query_vars 是一个简单的数组。

    【讨论】:

    • 非常感谢@jh1711,你让我的一天过得很好,正如你提到的unserialize.. 我尝试添加json_decode( stripslashes( $_POST['query'] ), true );,但是当我点击加载更多按钮时,会显示不同的帖子术语,那么如何使用json 从我过滤的当前术语中获取相同的帖子?
    • 我用 loadmore 脚本的 JS 更新了我的问题。
    • 我不知道为什么json 不适合你。任何破坏 json 的东西也应该破坏序列化的数据。您可以尝试将serialize(...) 替换为base64_encode(json_encode(...),并将unserialize(...) 替换为json_decode(base64_decode(...), true)。这应该避免引号在途中被斜线/不斜线的任何问题。但由于我不知道到底发生了什么,我不知道这是否会有所帮助。对不起。
    • 感谢您抽出宝贵时间 jh,unserialize 工作就像一个魅力 :),我尝试按照您所说的那样进行操作 $args = json_decode(base64_decode( stripslashes( $_POST['query']) ), true); ,但不起作用..是这样吗?
    • 您好,当我更改 echo json_encode( array( 'posts' =&gt; serialize( $wp_query-&gt;query_vars ), TO echo json_encode( array( 'posts' =&gt; json_encode( $wp_query-&gt;query_vars ), 时,它现在可以使用 json 了 :)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 2022-01-22
    • 2021-08-19
    • 2015-04-16
    • 1970-01-01
    • 2015-10-13
    相关资源
    最近更新 更多