Accettare una chiamata AJAX con dati del form serializzati
Sto cercando di passare dei dati form a un plugin WordPress tramite ajax e funziona correttamente, tranne quando i dati del form sono serializzati. In quel caso il server risponde con un messaggio di errore. Sono bloccato su questo problema da giorni, ma non riesco a farlo funzionare. Cosa sto sbagliando? Non può essere così difficile, giusto?
Ecco il messaggio di errore:
call_user_func_array() si aspetta che il parametro 1 sia una callback valida, la funzione 'process_request' non è stata trovata o il nome della funzione non è valido in X:\xampp\htdocs\testsite\wp-includes\plugin.php alla riga 406
La chiamata AJAX:
jQuery(document).ready(function($) {
nonce: whatever
//se uso questa variabile, funziona correttamente
var data = {action: 'process_request', add_my_data: 'whatever', 'my_data[name]':'whatever', my_nonce: nonce};
//se uso questa variabile, il server restituisce l'errore sopra citato
//poiché .serialize() non include il nome del pulsante submit
//e il form non contiene il nome della funzione da chiamare, li ho aggiunti manualmente alla stringa. nonce viene preso dal form.
var data2 ='action=process_request&add_my_data=whatever&' + $('#my-form').serialize();
$('.my_submit_button').click(function(event) {
event.preventDefault();
jQuery.ajax({
type : 'post',
url : ajaxurl,
timeout: 25000,
data : //data (funziona) o data2 (non funziona),
[...]
La cosa strana è che i dati post per 'data2' sembrano essere corretti e hanno la stessa sintassi di 'data'.
Ho controllato i dati post con firebug:
per 'data':
action=process_request&add_my_data=whatever&my_data%5Bname%5D=whatever&my_nonce=1b444dd703
per 'data2' (con il form serializzato, l'unica differenza che vedo è il referer):
action=process_request&add_my_data=whatever&my_data%5Bname%5D=whatever&my_nonce=1b444dd703&_wp_http_referer=%2Ftestsite%2Fadmin%2Ftestpage%2F
La funzione PHP che gestisce la richiesta:
function process_request() {
//validazione nonce omessa per leggibilità
if( isset ($_POST['add_my_data']) ) {
$this->add_info_array('placeholder', 'Database aggiornato');
}
//esegui alcune operazioni qui
die();
}
add_action('wp_ajax_process_request', 'process_request');
AGGIORNAMENTO: Il problema è il referer nella stringa che viene creata per 'data2'. Controlla il mio commento qui sotto.
Quando lavoro con AJAX e Form in WordPress mi piace codificare l'azione ajax direttamente nel form in modo che la serializzazione funzioni immediatamente. In realtà ho scritto un articolo su questo l'anno scorso: https://webdevstudios.com/2015/02/12/handling-ajax-in-wordpress/
Ma sei qui per le risposte, non per un articolo del blog, quindi ecco la parte essenziale. Hai tre componenti qui, la prima è il form HTML. Puoi sfruttare serialize()
inserendo l'azione in un campo nascosto del form, ecco un esempio:
<form class="my_form">
<?php wp_nonce_field( 'my_action_nonce' ); ?>
<input type="hidden" name="action" value="my_action" />
<!-- Altri campi qui... -->
<input type="submit" name="submit" value="Invia" class="submit_form_btn" />
</form>
Nota il campo nascosto chiamato action
. Ovviamente ho mantenuto wp_nonce_field()
per questioni di sicurezza.
La seconda parte è il jQuery vero e proprio, come detto prima non hai bisogno di accedere ad AJAX tramite l'oggetto jQuery originale poiché lo hai già passato come $
, ma non fa male, è solo una cattiva pratica.
jQuery( document ).ready( function( $ ) {
$( '.submit_form_btn' ).on( 'click', function( evt ) {
// Ferma l'invio predefinito del form
evt.preventDefault();
// Serializza l'intero form, che include l'azione
var serialized = $( '.my_form' ).serialize();
$.ajax( {
url: ajaxurl, // Questa variabile da qualche parte
method: 'POST',
data: serialized, // Qui ci sono i nostri dati serializzati
} ).done( function( result ){
// Gestisci il risultato qui...
} );
} );
} );
Ho cercato di commentare il codice al meglio, dovrebbe essere più chiaro, ma lasciami spiegare. Prima fermi l'invio del form con il metodo preventDefault()
dell'oggetto evt
(abbreviazione di event).
Poi serializzi i dati del form e li memorizzi in una variabile. Suppongo che potresti abbreviare e inserirli direttamente nell'oggetto data, ma dipende da te.
La parte finale, beh hai bisogno di vedere cosa stai inviando vero? È qui che error_log
e print_r
tornano utili, ecco come:
<?php
function handle_ajax() {
// Qui verifichi il tuo nonce
if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'my_action_nonce' ) ) {
// Puoi sia ritornare, sia usare l'utile json
wp_send_json_error();
}
// Qui dovresti ottenere TUTTI i tuoi dati in una variabile $_POST
// oppure puoi fare qualcosa come questo e controllare il tuo log degli errori
error_log( print_r( $_POST, 1 ) );
// Questo stamperà l'INTERA variabile $_POST nel tuo debug.log se lo hai
// abilitato, altrimenti va nel log degli errori PHP
}
add_action( 'wp_ajax_my_action', 'handle_ajax' );
Ora questo DOVREBBE gestire l'ajax per te, quello che fai con i dati dipende da te.

Perché stai usando jQuery.ajax
?
Quando definisci jQuery(document).ready(function($) {
... $
diventa la tua variabile globale jQuery.
WordPress jQuery noConflict Wrapper
La tua chiamata ajax dovrebbe assomigliare a questa:
$.ajax({
type : 'post',
url : ajaxurl,
etc : ....
Inoltre, non puoi semplicemente passare una stringa di variabili. Devi prima definirle in un oggetto e passare quello.
Prova questo:
get_data = $('#my-form').serialize();
var data = {action: 'process_request', add_my_data: get_data, my_nonce: nonce};
Non sono sicuro riguardo alla serializzazione però... pensavo che WordPress già lo facesse durante il processo di post ajax. Potresti aver bisogno di fare ulteriori ricerche su questo punto.

Avevi ragione riguardo alla variabile jQuery, ma non ha cambiato nulla, come ho detto, se non serializzato il tutto funziona perfettamente.
