Accettare una chiamata AJAX con dati del form serializzati

20 ott 2013, 01:42:21
Visualizzazioni: 23.9K
Voti: 1

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.

6
Commenti

Devi mostrare un po' più di codice, dov'è l'hook?

brasofilo brasofilo
20 ott 2013 02:13:17

È lì, semplicemente non l'avevo incluso sopra (ora l'ho incluso). Come ho detto, la funzione e la chiamata ajax funzionano, semplicemente non funziona con i dati post serializzati

JimQ JimQ
20 ott 2013 02:26:11

Il messaggio di errore dice che process_request() non è definita. Da dove viene questa funzione?

kaiser kaiser
20 ott 2013 02:51:10

Questa funzione si trova nel mio file del plugin.

JimQ JimQ
20 ott 2013 03:05:25

Bene, il referer nella stringa creata per 'data2' sembra essere il problema. Se sostituisco la parte serialized() con la stringa che ho ottenuto da Firebug e rimuovo il referer, improvvisamente funziona. Se lo lascio dentro, stesso problema descritto prima. Quindi la nuova domanda è: Perché il referer nella stringa fa sì che WordPress generi quel messaggio di errore e come posso evitare che venga incluso con serialize()? Non fa nemmeno parte del form, quindi da dove viene?

JimQ JimQ
20 ott 2013 15:53:47

Ok gente, ci stiamo avvicinando alla soluzione: stavo usando wp_nonce_field nel form, questo fa sì che WordPress crei un campo nascosto con il referer, quindi questo spiega da dove proviene. Ultima domanda rimanente: Perché il referer causa un problema?

JimQ JimQ
20 ott 2013 16:04:07
Mostra i restanti 1 commenti
Tutte le risposte alla domanda 2
0

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.

11 gen 2016 06:56:34
3

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.

20 ott 2013 02:45:38
Commenti

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

JimQ JimQ
20 ott 2013 03:14:45

scusa, questo era il primo commento, non potevo più modificarlo:

JimQ JimQ
20 ott 2013 03:21:03

Grazie per il suggerimento, ma se lo faccio, i dati serializzati() saranno definiti come valore di add_my_data. Così: add_my_data:action=process_request&add_my_data=whatever&...

JimQ JimQ
20 ott 2013 03:21:26