web-dev-qa-db-fra.com

Acceptez AJAX appel avec données de formulaire sérialisées

J'essaie de transmettre à un plugin wordpress des données de formulaire via ajax et tout fonctionne correctement. À moins que les données de formulaire ne soient sérialisées, le serveur répond par un message d'erreur. Cela fait des jours que je suis coincé avec ça, mais je ne peux pas le faire fonctionner. Qu'est-ce que je fais mal, cela ne peut pas être si difficile, non?

Voici le message d'erreur:

call_user_func_array () s'attend à ce que le paramètre 1 soit un rappel valide, fonction 'demande_processus' introuvable ou nom de fonction non valide dans X:\xampp\htdocs\testsite\wp-includes\plugin.php à la ligne 406

L'appel AJAX:

jQuery(document).ready(function($) {

nonce: whatever

//if i use this variable, it works fine 
var data = {action: 'process_request', add_my_data: 'whatever', 'my_data[name]':'whatever', my_nonce: nonce};

//if i use this variable, the server returns the above error .
//because .serialize() doesn't include the submit button's name
//and the form doesn't contain the name of the function to be called, i added them manually to the string. nonce is pulled from 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 (works) or data2 (doesn't work),
[...]

La chose étrange est que les données de publication pour 'data2' semblent être correctes et ont la même syntaxe que pour 'data'.

J'ai contrôlé les données de poste avec firebug:

pour 'données':

action=process_request&add_my_data=whatever&my_data%5Bname%5D=whatever&my_nonce=1b444dd703 

pour 'data2' (avec le formulaire sérialisé, la seule différence que je vois est le référant):

action=process_request&add_my_data=whatever&my_data%5Bname%5D=whatever&my_nonce=1b444dd703&_wp_http_referer=%2Ftestsite%2Fadmin%2Ftestpage%2F

La fonction PHP qui gère la demande:

function process_request() {

    //nonce validation left out for readability

    if( isset ($_POST['add_my_data']) ) {
        $this->add_info_array('placeholder', 'Database updated');
    }
            //do some stuff here
            die();
        }
      add_action('wp_ajax_process_request', 'process_request');

UPDATE: Le problème est le référant dans la chaîne créée pour 'data2'. Vérifiez mon commentaire ci-dessous.

1
JimQ

Lorsque je travaille avec AJAX et les formulaires dans WordPress, j'aime bien coder l'action ajax en formulaire, de sorte que la sérialisation fonctionne correctement. En fait, j’ai écrit un article à ce sujet l’année dernière: https://webdevstudios.com/2015/02/12/handling-ajax-in-wordpress/

Mais vous êtes ici pour obtenir des réponses, pas un article de blog, alors voici la brève partie de celui-ci. Vous avez trois parties ici, la première est le formulaire HTML. Vous pouvez tirer parti de serialize() en plaçant l'action dans un champ de formulaire masqué, en voici un exemple:

<form class="my_form">
    <?php wp_nonce_field( 'my_action_nonce' ); ?>
    <input type="hidden" name="action" value="my_action" />
    <!-- More fields here... -->
    <input type="submit" name="submit" value="Submit" class="submit_form_btn" />
</form>

Notez le champ de formulaire masqué nommé action. Bien sûr, j'ai gardé la wp_nonce_field() puisque depuis bien, les problèmes de sécurité.

La deuxième partie est le jQuery réel, comme indiqué précédemment, vous n'avez pas besoin d'accéder à AJAX via l'objet jQuery d'origine puisque vous l'avez déjà passé en tant que $, mais cela ne nuit pas à quoi que ce soit, mauvaise pratique.

jQuery( document ).ready( function( $ ) {
    $( '.submit_form_btn' ).on( 'click', function( evt ) {
        // Stop default form submission
        evt.preventDefault();
        // Serialize the entire form, which includes the action
        var serialized = $( '.my_form' ).serialize();
        $.ajax( {
            url: ajaxurl, // This variable somewhere
            method: 'POST',
            data: serialized, // This is where our serialized data is
        } ).done( function( result ){
            // Handle the result here...
        } );
    } );
} );

J'ai essayé de commenter le code du mieux que je pouvais, cela devrait avoir plus de sens, mais laissez-moi vous expliquer. Tout d’abord, vous arrêtez la soumission du formulaire par la méthode preventDefault() de l’objet evt (en abrégé événement).

Vous sérialisez ensuite les données de formulaire et les stockez dans une variable. Je suppose que vous pouvez le raccourcir et le déposer simplement dans l’objet de données, mais c’est à vous de décider.

La dernière partie, vous devez voir ce que vous publiez, non? C'est là que error_log et print_r sont utiles, voici comment:

<?php

function handle_ajax() {
    // Here you verify your nonce
    if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'my_action_nonce' ) ) {
        // You can either return, or use nifty json stuffs
        wp_send_json_error();
    }
    // Here you should get ALL your data in a $_POST variable
    // or you can actually do someting like this then check your error log

    error_log( print_r( $_POST, 1 ) );

    // This will print out the ENTIRE $_POST variable to your debug.log if you have it
    // enabled, if not, it goes to your PHP error log

}
add_action( 'wp_ajax_my_action', 'handle_ajax' );

Maintenant que DEVRAIT gérer votre ajax pour vous, ce que vous faites avec les données est à vous.

2
Jay Wood

Pourquoi utilisez-vous jQuery.ajax?

Lorsque vous définissez jQuery(document).ready(function($) {... $ devient votre variable globale jquery. WordPress jQuery noConflict Wrapper

Votre ajax devrait ressembler à ceci:

$.ajax({
type : 'post',
url : ajaxurl,
etc : ....

Ensuite, vous ne pouvez pas simplement passer une chaîne de variables. Vous devez d'abord les définir dans un objet et le transmettre.

Essaye ça:

get_data = $('#my-form').serialize();
var data = {action: 'process_request', add_my_data: get_data, my_nonce: nonce};

Pas sûr de la sérialisation cependant ... car je pensais que WordPress l'avait déjà fait lors du post-traitement ajax. Vous devrez peut-être faire plus de recherches là-bas.

0
josh