使用AJAX加载更多产品WooCommerce [英] Using AJAX to load more products WooCommerce

查看:43
本文介绍了使用AJAX加载更多产品WooCommerce的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用AJAX在WooCommerce存档中加载更多产品.我曾经在此页面上使用AJAX进行过加载更多".我在很大程度上使用了相同的代码,只是更改了 WP_Query 参数以适合我的需要.我不明白为什么我的代码无法正常工作.

I am using AJAX to load more products on a WooCommerce archive. I have used AJAX to "Load More" once before on this page. I have used the same code for the most part, just altered the WP_Query arguments to suit my needs. I can't understand why my code doesn't work.

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 上访问开发站点,而我一直在使用在红茶" 页中我的测试.任何帮助将不胜感激.

The AJAX call runs successfully but doesn't return what I'd expect it to. I'd expect it to return the next product from the current category, instead it returns a product from a different category. The development site is accessible on http://leaf.kalodigital.co.uk and I have been using the "Black Tea" page in my testing. Any help would be greatly appreciated.

推荐答案

方法

经过进一步研究,我发现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 对象期望的格式不匹配.

Method

After some further research, I found that WooCommerce contains a class names WC_Poduct_Query. Following their documentation, found here, I rebuilt my query. This was working in the sense that it was querying for the correct products and returns the ones I'd expect it to as an array of WC_Product_Variable Objects. I proceeded to, within a foreach loop, use setup_postdata( $post ); to set the product Objects up so that I could use the wc_get_template_parts(); function to call the content-product.php template to format the output of the data. I found that this didn't work, although I couldn't figure to why this was the case, using setup-postdata(); was causing the object to turn into [{id:0,filter:raw},{id:0,filter:raw}]. I imagine this would be related to the WC_Product_Variable Objects not matching the expect format that setup_postdata(); usually expects from a WP_Post Object.

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

Nonetheless, I reverted to using WP_Query for my query, rebuilt the query script from scratch and, would you believe it, everything worked as expected to. Below is my working code to AJAX load the next "bunch" of products on any WooCommerce Archive page, at the click of a button.

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代码,可以将该解决方案变成无限滚动"系统,而不是加载更多"按钮解决方案.请随时在可能的地方重用此代码!

Use Cases

By refactoring the supplied AJAX code, it would be possible to turn this solution into an "infinite scrolling" system as opposed to a "Load More" button solution. Please feel free to reuse this code where it may see fit!

这篇关于使用AJAX加载更多产品WooCommerce的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆