我正在使用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"页面。任何帮助将不胜感激。
答案 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代码,可以将该解决方案变成“无限滚动”系统,而不是“加载更多”按钮解决方案。请随时在可能的地方重用此代码!