我一直在WordPress中深入研究AJAX,并学习了许多教程,但每个请求都会返回400个错误。
在我的functions.php 我添加了以下内容:
Step 1 - 向WordPress注册并添加脚本
/**
* Initialize the JavaScript we need for loading more
*
* @return void
*/
function ajax_load_more_init()
{
// Register and enqueue the script we need for load more
wp_register_script(\'ajax-load-more-script\', get_template_directory_uri() . \'/assets/scripts/ajax-load-more.js\', array(\'jquery\'));
wp_enqueue_script(\'ajax-load-more-script\');
// Localize the script so we can access tthe variables in PHP
wp_localize_script(\'ajax-load-more-script\', \'ajax_load_more_object\', array(
\'ajax_url\' => admin_url(\'admin-ajax.php\'),
));
}
Step 2 - 将实际脚本排队
/**
* Add AJAX loader to scripts
*/
add_action(\'wp_enqueue_scripts\', \'ajax_load_more_init\');
Step 3 - 允许在前端使用AJAX
// AJAX Hook for users
add_action(\'wp_ajax_ajax_load_more\', \'ajax_load_more\');
add_action(\'wp_ajax_nopriv_ajax_load_more\', \'ajax_load_more\');
Step 4 - 一个非常简单的测试函数
/**
* The backend PHP to actually load more posts
*
* @return void
*/
function ajax_load_more()
{
echo "TESTING";
wp_die();
}
在实际的AJAX脚本中,我有以下内容:
jQuery(document).ready(function ($) {
// Initialize Isotope as $grid
const $grid = $(\'#grid\').isotope({
itemSelector: \'.grid-item\',
percentagePosition: true,
animationEngine: \'best-available\', //CSS3 if browser supports it, jQuery otherwise
animationOptions: {
duration: 800,
},
masonry: {
columnWidth: \'.grid-item\',
gutter: 30,
},
})
var has_run = false;
var init_offset = 0;
// Hook into click event
$(\'button.load-more-posts\').click(function (e) {
e.preventDefault();
var button = $(this);
var nonce = $(this).data("nonce");
console.log(\'Nonce is: \' + nonce);
// Disable the button
button.prop("disabled", true);
// Check the offset
if (has_run == false) {
button.data(\'offset\', $(this).data("offset"));
init_offset = $(this).data("offset");
}
console.log(\'Initial offset is: \' + init_offset);
console.log(\'Initial offset is: \' + button.data(\'offset\'));
// Perform AJAX request
$.ajax({
type: \'POST\',
dataType: \'json\',
url: ajax_load_more_object.ajax_url,
contentType: \'application/json; charset=utf-8\',
data: {
action: \'ajax_load_more\',
security: nonce,
init_offset: init_offset,
offset: button.data(\'offset\'),
},
beforeSend: function (xhr) {
console.log(\'Loading more posts...\')
button.text(\'Loading\');
},
success: function (response) {
console.log(response);
// Undo Button Disable
button.prop("disabled", false);
// Set Offset
button.data("offset", offset + 10);
// Script has run
has_run = true;
return false;
},
error: function (xhr, status, error) {
console.log(xhr.responseText);
}
});
});
});
正如您在
$ajax
调用,url为
admin-ajax
动作是
wp_ajax_nopriv_ajax_load_more
.
nonce来自前端的按钮,如下所示:
<button class="load-more-posts" data-nonce="<?php echo wp_create_nonce(\'load_more_ajax\'); ?>" data-offset="10">Load More Posts</button>
My working code
因此,由于大家的共同意见,我能够想出一个解决方案,我将在下面详细介绍:
在函数中。php(应该在插件中)
/**
* Additional thumbnail sizes
*/
add_theme_support(\'post-thumbnails\');
add_image_size(\'post-thumbnail-square\', 300, 300, true);
/**
* Initialize the JavaScript we need for loading more
*
* @return void
*/
function ajax_load_more_init()
{
// Register and enqueue the script we need for load more
wp_register_script(\'ajax-load-more-script\', get_template_directory_uri() . \'/assets/scripts/ajax-load-more.js\', array(\'jquery\'));
wp_enqueue_script(\'ajax-load-more-script\');
// Localize the script so we can access tthe variables in PHP
wp_localize_script(\'ajax-load-more-script\', \'ajax_load_more_object\', array(
\'ajax_url\' => admin_url(\'admin-ajax.php\'),
));
}
/**
* Add AJAX loader to scripts
*/
add_action(\'wp_enqueue_scripts\', \'ajax_load_more_init\');
/**
* Allow AJAX to be used on the front end
*/
add_action(\'wp_ajax_ajax_load_more_posts\', \'ajax_load_more_posts_callback\');
add_action(\'wp_ajax_nopriv_ajax_load_more_posts\', \'ajax_load_more_posts_callback\');
/**
* The backend PHP to actually load more posts
*
* @return void
*/
function ajax_load_more_posts_callback()
{
// First check the nonce, if it fails the function will break
check_ajax_referer(\'ajax_load_more_posts\', \'security\');
// Get the data we have from the load more button
$offset = $_POST[\'offset\'];
$init_offset = $_POST[\'init_offset\'];
// Get posts with given offset
if ($offset != null && absint($offset) && $init_offset != null && absint($init_offset)) {
// Finally, we\'ll set the query arguments and instantiate WP_Query
$args = array(
\'post_type\' => \'post\',
\'posts_per_page\' => $init_offset,
\'offset\' => $offset
);
$post_list = array();
$query = new WP_Query($args);
if ($query->have_posts()) :
while ($query->have_posts()) : $query->the_post();
//$categories = get_the_categories();
$post_list[] = array(
\'category\' => get_the_category(),
\'title\' => get_the_title(),
\'introduction\' => get_field(\'introduction\'),
\'date\' => get_the_date(),
\'permalink\' => get_permalink(),
\'thumbnail\' => get_the_post_thumbnail(),
);
endwhile;
endif;
echo json_encode($post_list);
wp_die();
}
}
在我的ajax加载程序脚本中
jQuery(document).ready(function ($) {
var has_run = false;
var init_offset = 0;
// Hook into click event
$(\'button.load-more-posts\').click(function (e) {
var $grid = $(\'#grid\').isotope({
itemSelector: \'.grid-item\',
});
e.preventDefault();
var button = $(this);
var nonce = $(this).data("nonce");
// Disable the button
button.prop("disabled", true);
// Check the offset
if (has_run == false) {
button.data(\'offset\', $(this).data("offset"));
init_offset = $(this).data("offset");
}
// Perform AJAX request
$.ajax({
type: \'POST\',
dataType: \'json\',
url: ajax_load_more_object.ajax_url,
data: {
action: \'ajax_load_more_posts\',
security: nonce,
init_offset: init_offset,
offset: button.data(\'offset\'),
},
beforeSend: function (xhr) {
console.log(\'Loading more posts...\')
button.text(\'Loading\');
},
success: function (response) {
console.log(response);
button.text(\'Load more\');
// An array to store new items added via AJAX
var new_items = [];
// Run through JSON
$.each(response, function (key, value) {
var $new_item = $(`<div class="grid-item article-post-card ${value.category[0][\'slug\']}">
<a class="article-post-card__anchor" href=" ${value.permalink}" alt="${value.title}">
<div class="article-post-card__featured-image-container">
<div class="article-post-card__overlay"></div>
<div class="article-post-card__featured-image">
${value.thumbnail}
</div>
<div class="article-post-card__category-label">
${value.category[0][\'name\']}
</div>
</div>
<div class="article-post-card__content-wrapper">
<div class="article-post-card__publish-date">
<time class="updated" datetime="">${value.date}</time>
</div>
<div class="article-post-card__title">
${value.title}
</div>
<div class="article-post-card__excerpt">
${value.introduction}
</div>
</div>
</a>
</div>`);
new_items.push($new_item[0]);
});
// Add the new items to the grid
$grid
.isotope(\'insert\', new_items)
.imagesLoaded().progress(function () {
$grid.isotope(\'layout\');
});
// Undo Button Disable
button.prop("disabled", false);
// Set Offset
var offset = button.data("offset");
button.data("offset", offset + 10);
// Script has run
has_run = true;
return false;
},
error: function (xhr, status, error) {
console.log("There was an error", error);
}
});
});
});
如果你们能提出批评,我想这对其他人也会很有用。
最合适的回答,由SO网友:Sally CJ 整理而成
我没有测试您的代码,但我注意到的一个问题是contentType
您的$.ajax()
电话:
contentType: \'application/json; charset=utf-8\',
因为这样,(从PHP方面)操作(即。
ajax_load_more
) 在中不可用
$_REQUEST[\'action\']
WordPress使用哪个来确定调用的AJAX操作,当操作未知时,WordPress会抛出错误
400 Bad Request
, 在您的情况下,这将转换为“未知的AJAX操作”。
你应该省略contentType
属性,或者不要将其设置为JSON内容类型字符串
还有,虽然你只是在测试ajax_load_more()
, 确保返回正确的JSON响应/字符串,因为dataType
是json
.
我希望这对你有帮助。:)
dataType
(默认值:Intelligent Guess (xml, json, script, or html)
)您希望从服务器返回的数据类型。如果未指定,jQuery将尝试根据响应的MIME类型推断它
contentType
(默认值:\'application/x-www-form-urlencoded; charset=UTF-8\'
)向服务器发送数据时,请使用此内容类型。默认值为“application/x-www-form-urlencoded;charset=UTF-8”,这在大多数情况下都适用。如果将内容类型显式传递给$.ajax()
, 然后总是将其发送到服务器(即使没有发送数据)。
So
dataType
是来自AJAX响应的内容的内容类型(MIME),而
contentType
是要发送给PHP/服务器端函数的内容的内容类型(即
ajax_load_more()
在您的情况下)。
更新,以便使用错误的内容类型使标题无法读取?
不,这不是关于标题变得不可读的问题-(请求)标题在PHP中总是可读的。只是request payload (在JSON中)不受WordPress AJAX支持-只有请求主体。但您当然可以将表单字段数据/值作为JSON发送-例如,myField: \'{"foo":"bar","baz":1}\'
. 只是不要将内容类型头设置为JSON。
但是,如果您确实必须发送JSON请求负载,而不是标准的URL编码表单数据(即请求正文),那么您可以将AJAX操作附加到AJAX URL,例如。/wp-admin/admin-ajax.php?action=ajax_load_more
. 那样你就不会出错400
; 然而,这取决于你retrieve/parse JSON请求负载。。
请求有效负载(JSON)
jQuery.ajax({
type: \'POST\',
url: \'/wp-admin/admin-ajax.php?action=ajax_load_more\',
contentType: \'application/json; charset=utf-8\',
data: {
action: \'ajax_load_more\',
foo: \'bar\',
}
});
请求正文(表单数据)
jQuery.ajax({
type: \'POST\',
url: \'/wp-admin/admin-ajax.php\',
data: {
action: \'ajax_load_more\',
foo: \'bar\',
}
});