使用AJAX加载更多产品WooCommerce

时间:2018-09-05 15:56:52

标签: php jquery ajax wordpress woocommerce

我正在使用AJAX在WooCommerce存档中加载更多产品。我之前曾经在this page上使用AJAX来“加载更多”。我在大多数情况下使用了相同的代码,只是更改了WP_Query参数以满足我的需要。我不明白为什么我的代码不起作用。

JS

/**
 * AJAX Load (Lazy Load) events
 */

$('#load-more').click( function(e){
    e.preventDefault();
    ajax_next_posts()
    $('body').addClass('ajaxLoading');
});

var ajaxLock = false; // ajaxLock is just a flag to prevent double clicks and spamming

if( !ajaxLock ) {

function ajax_next_posts() {

    ajaxLock = true;

    // How many posts there's total
    var totalPosts = parseInt( jQuery( '#found-posts' ).text() );

    // How many have been loaded
    var postOffset = jQuery( 'li.product' ).length

    // How many do you want to load in single patch
    var postsPerPage = 1;

    // Ajax call itself
    $.ajax({
        method: 'POST',
        url: leafshop.ajax_url,
        data: {
            action: 'ajax_next_posts',
            post_offset: postOffset,
            posts_per_page: postsPerPage,
            product_cat: cat_id
        },
        dataType: 'json'
    })
    .done( function( response ) { // Ajax call is successful
        // console.log( response );

        // Add new posts
        jQuery( '.product-grid' ).append( response[0] );

        // Log SQL query
        jQuery( '#query > pre' ).text( response[2] );

        // Update the count of total posts
        // jQuery( '#found-posts' ).text( response[1] );

        ajaxLock = false;

        console.log( 'Success' );

        $('body').removeClass('ajaxLoading');

        // How many posts there's total
        var totalPosts = parseInt( jQuery( '#found-posts' ).text() );
        console.log( "Total Posts: " + totalPosts );

        // How many have been loaded
        var postOffset = jQuery( 'li.product' ).length
            console.log( "Posts currently showing: " + postOffset );

        // Hide button if all posts are loaded
        if( totalPosts < postOffset + ( 1 * postsPerPage ) ) {
            jQuery( '#load-more' ).fadeOut();
        }

    })
    // .fail( function() {
    .fail( function(jqXHR, textStatus, errorThrown) { // Ajax call is not successful, still remove lock in order to try again

        ajaxLock = false;

        console.log(XMLHttpRequest);
        console.log(textStatus);
        console.log(errorThrown);

        console.log( 'Failed' );

    });
}
}

PHP

<?php

/**
 * Load next 12 products using AJAX
 */
function ajax_next_posts() {
    global $wpdb;
    // Build query
    $args = array(
        'post_type' =>  'product'
    );
// Get offset
if( !empty( $_POST['post_offset'] ) ) {

    $offset = $_POST['post_offset'];
    $args['offset'] = $offset;

    // Also have to set posts_per_page, otherwise offset is ignored
    $args['posts_per_page'] = 12;
}

// Get posts per page
if( !empty( $_POST['posts_per_page'] ) ) {
    // Also have to set posts_per_page, otherwise offset is ignored
    $args['posts_per_page'] = $_POST['posts_per_page'];
}

// Set tax query if on cat page
if( !empty( $_POST['product_cat'] ) ){
    $args['tax_query'] = array(
                            'taxonomy'          =>  'product_cat',
                            'terms'             =>  array( (int)$_POST['product_cat'] ),
                            'field'             =>  'id',
                            'operator'          =>  'IN',
                            'include_children'  =>  1
                        );
}

$count_results = '0';

$ajax_query = new WP_Query( $args );

// Results found
if ( $ajax_query->have_posts() ) {
    $count_results = $ajax_query->found_posts;

    // Start "saving" results' HTML
    $results_html = '';
    ob_start();

    while( $ajax_query->have_posts() ) { 
        $ajax_query->the_post();
        echo wc_get_template_part( 'content', 'product' );
    }

    // "Save" results' HTML as variable
    $results_html = ob_get_clean();
}

// Build ajax response
$response = array();

// 1. value is HTML of new posts and 2. is total count of posts
global $wpdb;
array_push ( $response, $results_html, $count_results, $wpdb->last_query );
echo json_encode( $response );

// Always use die() in the end of ajax functions
die();  
}
add_action('wp_ajax_ajax_next_posts', 'ajax_next_posts');
add_action('wp_ajax_nopriv_ajax_next_posts', 'ajax_next_posts');

AJAX调用成功运行,但没有返回我期望的结果。我希望它返回当前类别的下一个产品,而不是返回其他类别的产品。可在http://leaf.kalodigital.co.uk上访问开发站点,并且在测试中一直使用"Black Tea"页面。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

方法

经过进一步研究,我发现WooCommerce包含一个类名WC_Poduct_Query。根据他们的文档(在此处找到),我重建了查询。该的意义上是在查询正确的产品,并以WC_Product_Variable对象的数组形式返回我期望的产品。我继续在foreach循环中,使用setup_postdata( $post );设置产品对象,以便可以使用wc_get_template_parts();函数调用content-product.php模板来格式化输出数据。我发现这是行不通的,尽管我不知道为什么会这样,使用setup-postdata();导致对象变成[{id:0,filter:raw},{id:0,filter:raw}]。我想这可能与WC_Product_Variable对象不符合setup_postdata();通常期望的WP_Post对象期望格式有关。

尽管如此,我还是恢复使用WP_Query进行查询,从头开始重建查询脚本,并且您相信它,一切都能按预期进行。下面是我的工作代码,只需单击一下按钮,即可在任何 WooCommerce存档页面上加载AJAX的下一批产品。

代码

JS

/**
 * AJAX Load (Lazy Load) events
 */

 //--   Settings

// How many do you want to load each button click?
var postsPerPage = 12;

//--    /Settings

// How many posts there's total
var totalPosts = parseInt( jQuery( '#found-posts' ).text() );

// if( totalPosts == postOffset ) {
//  jQuery( '#load-more' ).fadeOut();
// }

$('#load-more').click( function(e){
    e.preventDefault();

    // Get current category
    var cat_id  =   $(this).data('product-category');


ajax_next_posts( cat_id );
    $('body').addClass('ajaxLoading');
});

var ajaxLock = false; // ajaxLock is just a flag to prevent double clicks and spamming

if( !ajaxLock ) {

    function ajax_next_posts( cat_id ) {

        ajaxLock = true;

        // How many have been loaded
        var postOffset = jQuery( 'li.product' ).length;

        // Ajax call itself
        $.ajax({
            method: 'POST',
            url: leafshop.ajax_url,
            data: {
                action: 'ajax_next_posts',
                post_offset: postOffset,
                posts_per_page: postsPerPage,
                product_cat: cat_id
            },
            dataType: 'json'
        })
        .done( function( response ) { // Ajax call is successful

            // Add new posts
            jQuery( '.product-grid' ).append( response[0] );

            // Update Post Offset
            var postOffset = jQuery( 'li.product' ).length;

            ajaxLock = false;

            console.log( 'Success' );

            $('body').removeClass('ajaxLoading');

            // How many posts there's total
            console.log( "Total Posts: " + totalPosts );

            // How many have been loaded
            var postOffset = jQuery( 'li.product' ).length
            console.log( "Posts on Page: " + postOffset );

            // Hide button if all posts are loaded
            if( ( totalPosts - postOffset ) <= 0 ) {
                jQuery( '#load-more' ).fadeOut();
            }

        })
        // .fail( function() {
        .fail( function(jqXHR, textStatus, errorThrown) { // Ajax call is not successful, still remove lock in order to try again

            ajaxLock = false;

            console.log(XMLHttpRequest);
            console.log(textStatus);
            console.log(errorThrown);

            console.log( 'Failed' );

        });
    }
}

PHP

<?php

/**
 * Load next 12 products using AJAX
 */
function ajax_next_posts() {
global $product;
// Build Query
    $args = array(
            'post_type'             =>  'product',
            'posts_per_page'        =>  (int)$_POST['posts_per_page'],
            'orderby'               =>  'title',
            'order'                 =>  'ASC',
            'offset'                =>  (int)$_POST['post_offset'],
        );

if( !empty( $_POST['product_cat'] ) ) {
    $args['tax_query'] = array(
                            'relation'  => 'AND',
                                array (
                                    'taxonomy'  =>  'product_cat',
                                    'field' =>  'slug',
                                    'terms' => $_POST['product_cat'],
                                    'operator'  =>  'IN'
                                ),
                        );
}

$count_results = '0';

$ajax_query = new WP_Query( $args );

// Results found
if( $ajax_query->have_posts() ){

    // Start "saving" results' HTML
    $results_html = '';
    ob_start();

    while( $ajax_query->have_posts() ) {

        $ajax_query->the_post();
        echo wc_get_template_part( 'content', 'product' );

    }
    wp_reset_postdata();

    // "Save" results' HTML as variable
    $results_html = ob_get_clean();

} else {

    // Start "saving" results' HTML
    $results_html = '';
    ob_start();

    echo "none found!";

    // "Save" results' HTML as variable
    $results_html = ob_get_clean();

}

// Build ajax response
$response = array();

// 1. value is HTML of new posts and 2. is total count of posts
array_push ( $response, $results_html );
echo json_encode( $response );

// Always use die() in the end of ajax functions
die();
}
add_action('wp_ajax_ajax_next_posts', 'ajax_next_posts');
add_action('wp_ajax_nopriv_ajax_next_posts', 'ajax_next_posts');

用例

通过重构提供的AJAX代码,可以将该解决方案变成“无限滚动”系统,而不是“加载更多”按钮解决方案。请随时在可能的地方重用此代码!