Ecco una risposta molto lunga alla mia domanda che va oltre la semplice questione della generazione di nonces uniche per le successive richieste Ajax. Questa è una funzione "aggiungi ai preferiti" che è stata resa generica ai fini della risposta (la mia funzione consente agli utenti di aggiungere gli ID post degli allegati fotografici a un elenco di preferiti, ma ciò potrebbe applicarsi a una varietà di altre funzionalità che si basano su Ajax). Ho codificato questo come un plug-in autonomo e mancano alcuni elementi, ma dovrebbero essere sufficienti i dettagli per fornire l'essenza se si desidera replicare la funzionalità. Funzionerà su un singolo post / pagina, ma funzionerà anche in elenchi di post (ad esempio puoi aggiungere / rimuovere elementi ai preferiti in linea tramite Ajax e ogni post avrà il suo nonce unico per ogni richiesta Ajax). Tieni presente che ci '
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');
favourites.js (molte cose di debug che possono essere rimosse)
$(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
});
Funzioni (display front-end e azione Ajax)
Per visualizzare il link Aggiungi / Rimuovi Preferiti, chiamalo semplicemente sulla tua pagina / post tramite:
if (function_exists('myFavoritesLink') {
myFavoritesLink($user_ID, $post->ID);
}
Funzione display frontale:
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";
}
}
Funzione di azione 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');