这里有一个关于我自己问题的很长的答案,它不仅仅是解决为后续Ajax请求生成唯一nonce的问题。这是一个“添加到收藏夹”功能,出于回答的目的,它是通用的(我的功能允许用户将照片附件的帖子ID添加到收藏夹列表中,但这可能适用于依赖Ajax的其他各种功能)。我将其编码为一个独立的插件,缺少了一些项目——但如果您想复制该功能,这应该足够详细,可以提供要点。它可以在单个帖子/页面上运行,但也可以在帖子列表中运行(例如,您可以通过Ajax在线向收藏夹添加/删除项目,每个帖子对于每个Ajax请求都有自己独特的nonce)。请记住,可能有一种更有效和/或更优雅的方法可以做到这一点,目前这种方法仅适用于Ajax——我还没有费心处理非Ajax$\\u POST数据。
scripts.php
/**
* Enqueue front-end jQuery
*/
function enqueueFavoritesJS()
{
// Only show Favorites Ajax JS if user is logged in
if (is_user_logged_in()) {
wp_enqueue_script(\'favorites-js\', MYPLUGIN_BASE_URL . \'js/favorites.js\', array(\'jquery\'));
wp_localize_script(\'favorites-js\', \'ajaxVars\', array(\'ajaxurl\' => admin_url(\'admin-ajax.php\')));
}
}
add_action(\'wp_enqueue_scripts\', \'enqueueFavoritesJS\');
favorites.js (大量可以删除的调试内容)
$(document).ready(function()
{
// Toggle item in Favorites
$(".faves-link").click(function(e) {
// Prevent self eval of requests and use Ajax instead
e.preventDefault();
var $this = $(this);
console.log("Starting click event...");
// Fetch initial variables from the page
post_id = $this.attr("data-post-id");
user_id = $this.attr("data-user-id");
the_toggle = $this.attr("data-toggle");
ajax_nonce = $this.attr("data-nonce");
console.log("data-post-id: " + post_id);
console.log("data-user-id: " + user_id);
console.log("data-toggle: " + the_toggle);
console.log("data-nonce: " + ajax_nonce);
console.log("Starting Ajax...");
$.ajax({
type: "POST",
dataType: "json",
url: ajaxVars.ajaxurl,
data: {
// Send JSON back to PHP for eval
action : "myFavorites",
post_id: post_id,
user_id: user_id,
_ajax_nonce: ajax_nonce,
the_toggle: the_toggle
},
beforeSend: function() {
if (the_toggle == "y") {
$this.text("Removing from Favorites...");
console.log("Removing...");
} else {
$this.text("Adding to Favorites...");
console.log("Adding...");
}
},
success: function(response) {
// Process JSON sent from PHP
if(response.type == "success") {
console.log("Success!");
console.log("New nonce: " + response.newNonce);
console.log("New toggle: " + response.theToggle);
console.log("Message from PHP: " + response.message);
$this.text(response.message);
$this.attr("data-toggle", response.theToggle);
// Set new nonce
_ajax_nonce = response.newNonce;
console.log("_ajax_nonce is now: " + _ajax_nonce);
} else {
console.log("Failed!");
console.log("New nonce: " + response.newNonce);
console.log("Message from PHP: " + response.message);
$this.parent().html("<p>" + response.message + "</p>");
_ajax_nonce = response.newNonce;
console.log("_ajax_nonce is now: " + _ajax_nonce);
}
},
error: function(e, x, settings, exception) {
// Generic debugging
var errorMessage;
var statusErrorMap = {
\'400\' : "Server understood request but request content was invalid.",
\'401\' : "Unauthorized access.",
\'403\' : "Forbidden resource can\'t be accessed.",
\'500\' : "Internal Server Error",
\'503\' : "Service Unavailable"
};
if (x.status) {
errorMessage = statusErrorMap[x.status];
if (!errorMessage) {
errorMessage = "Unknown Error.";
} else if (exception == \'parsererror\') {
errorMessage = "Error. Parsing JSON request failed.";
} else if (exception == \'timeout\') {
errorMessage = "Request timed out.";
} else if (exception == \'abort\') {
errorMessage = "Request was aborted by server.";
} else {
errorMessage = "Unknown Error.";
}
$this.parent().html(errorMessage);
console.log("Error message is: " + errorMessage);
} else {
console.log("ERROR!!");
console.log(e);
}
}
}); // Close $.ajax
}); // End click event
});
Functions (front-end display & Ajax action)
要输出“添加/删除收藏夹”链接,只需通过以下方式在页面/帖子上调用它:
if (function_exists(\'myFavoritesLink\') {
myFavoritesLink($user_ID, $post->ID);
}
前端显示功能:
function myFavoritesLink($user_ID, $postID)
{
global $user_ID;
if (is_user_logged_in()) {
// Set initial element toggle value & link text - udpated by callback
$myUserMeta = get_user_meta($user_ID, \'myMetadata\', true);
if (is_array($myUserMeta[\'metadata\']) && in_array($postID, $myUserMeta[\'metadata\'])) {
$toggle = "y";
$linkText = "Remove from Favorites";
} else {
$toggle = "n";
$linkText = "Add to Favorites";
}
// Create Ajax-only nonce for initial request only
// New nonce returned in callback
$ajaxNonce = wp_create_nonce(\'myplugin_myaction_\' . $postID);
echo \'<p class="faves-action"><a class="faves-link"\'
. \' data-post-id="\' . $postID
. \'" data-user-id="\' . $user_ID
. \'" data-toggle="\' . $toggle
. \'" data-nonce="\' . $ajaxNonce
. \'" href="#">\' . $linkText . \'</a></p>\' . "\\n";
} else {
// User not logged in
echo \'<p>Sign in to use the Favorites feature.</p>\' . "\\n";
}
}
Ajax操作功能:
/**
* Toggle add/remove for Favorites
*/
function toggleFavorites()
{
if (is_user_logged_in()) {
// Verify nonce
$ajaxNonce = \'myplugin_myaction\' . $_POST[\'post_id\'];
if (! wp_verify_nonce($_POST[\'_ajax_nonce\'], $ajaxNonce)) {
exit(\'Sorry!\');
}
// Process POST vars
if (isset($_POST[\'post_id\']) && is_numeric($_POST[\'post_id\'])) {
$postID = $_POST[\'post_id\'];
} else {
return;
}
if (isset($_POST[\'user_id\']) && is_numeric($_POST[\'user_id\'])) {
$userID = $_POST[\'user_id\'];
} else {
return;
}
if (isset($_POST[\'the_toggle\']) && ($_POST[\'the_toggle\'] === "y" || $_POST[\'the_toggle\'] === "n")) {
$toggle = $_POST[\'the_toggle\'];
} else {
return;
}
$myUserMeta = get_user_meta($userID, \'myMetadata\', true);
// Init myUserMeta array if it doesn\'t exist
if ($myUserMeta[\'myMetadata\'] === \'\' || ! is_array($myUserMeta[\'myMetadata\'])) {
$myUserMeta[\'myMetadata\'] = array();
}
// Toggle the item in the Favorites list
if ($toggle === "y" && in_array($postID, $myUserMeta[\'myMetadata\'])) {
// Remove item from Favorites list
$myUserMeta[\'myMetadata\'] = array_flip($myUserMeta[\'myMetadata\']);
unset($myUserMeta[\'myMetadata\'][$postID]);
$myUserMeta[\'myMetadata\'] = array_flip($myUserMeta[\'myMetadata\']);
$myUserMeta[\'myMetadata\'] = array_values($myUserMeta[\'myMetadata\']);
$newToggle = "n";
$message = "Add to Favorites";
} else {
// Add item to Favorites list
$myUserMeta[\'myMetadata\'][] = $postID;
$newToggle = "y";
$message = "Remove from Favorites";
}
// Prep for the response
// Nonce for next request - unique with microtime string appended
$newNonce = wp_create_nonce(\'myplugin_myaction_\' . $postID . \'_\'
. str_replace(\'.\', \'\', gettimeofday(true)));
$updateUserMeta = update_user_meta($userID, \'myMetadata\', $myUserMeta);
// Response to jQuery
if($updateUserMeta === false) {
$response[\'type\'] = "error";
$response[\'theToggle\'] = $toggle;
$response[\'message\'] = "Your Favorites could not be updated.";
$response[\'newNonce\'] = $newNonce;
} else {
$response[\'type\'] = "success";
$response[\'theToggle\'] = $newToggle;
$response[\'message\'] = $message;
$response[\'newNonce\'] = $newNonce;
}
// Process with Ajax, otherwise process with self
if (! empty($_SERVER[\'HTTP_X_REQUESTED_WITH\']) &&
strtolower($_SERVER[\'HTTP_X_REQUESTED_WITH\']) == \'xmlhttprequest\') {
$response = json_encode($response);
echo $response;
} else {
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
exit();
} // End is_user_logged_in()
}
add_action(\'wp_ajax_myFavorites\', \'toggleFavorites\');