web-dev-qa-db-fra.com

La méthode correcte pour passer les vars de requête dans AJAX en utilisant ajaxurl

OK, je ne savais pas comment nommer ce sujet.

J'essaie de remplacer le comportement par défaut avec ajax. Le problème ici n'est pas réellement un problème, mais un souhait de plus.

J'ai cette URL:

<a href="http://example.com/?reaction=smk_remove_post&id=1226&_nonce=7be82cd4a0" class="smk-remove-post">Remove post</a>

Dans le functions.php j'ai cette fonction et l'appel juste après:

function smk_remove_post(){
    if( !empty( $_GET['reaction'] ) && 'smk_remove_post' == $_GET['reaction'] && !empty( $_GET['id'] ) ){
        if( current_user_can('edit_others_posts') && !empty($_GET['_nonce']) ){
            if( wp_verify_nonce( esc_html( $_GET['_nonce'] ), 'smk_remove_post' ) ){
                // Delete the post
                wp_delete_post( absint( $_GET['id'] ), true );
            }
        }
    }
}
smk_remove_post();

Maintenant, si je clique sur le lien, le message avec l'ID 1226 sera supprimé. Tout est OK. La tâche est terminée avec succès et la page est rechargée.

Voici où j'ai besoin de l'AJAX. Je veux traiter cette URL en utilisant ajax et ne pas recharger la page, et obtenir une réponse appropriée .

J'ai ajouté ce script jQuery:

function smk_remove_post(){
    $('.smk-remove-post').on( 'click', function( event ){
        event.preventDefault();
        var _this = $(this);

        jQuery.ajax({
            type: "GET",
            url: _this.attr('href'),
            success: function(response){
                console.log(response);
                _this.text('All great, the post is removed.');
            }
        });
    });
}
smk_remove_post();

Tout fonctionne comme prévu. Le message est supprimé via ajax et il n'est pas nécessaire de recharger la page. Mais je ne peux pas obtenir une réponse appropriée, mais au lieu de cela, je récupère l'intégralité de la source HTML de la page en cours.

Je sais que je devrais utiliser admin-ajax.php (ajaxurl), mais comment le faire? Je dois envoyer la requête à partir de l'URL et obtenir la réponse.

Voici ce que j'ai essayé:

J'ai ajouté ceci au script jQuery ci-dessus:

data: {
    'action': 'smk_remove_post_ajax',
},

Et ceci au PHP:

function smk_remove_post_ajax(){
    smk_remove_post();
    die();
}
add_action('wp_ajax_smk_remove_post_ajax', 'smk_remove_post_ajax');

Ça ne marche pas. Il est ignoré, l'appel précédent est exécuté, comme cela se ferait sans ajax.

Je comprends que je dois en quelque sorte envoyer la requête à admin-ajax.php à la place, mais comment?

5
Andrei Surdu

Je l'ai finalement eu.

La première erreur a été de traiter deux fois la même fonction. Je l'ai appelé une fois après la fonction et une fois de plus en action ajax. Ainsi, lors de l'utilisation de l'appel ajax, la fonction a été exécutée deux fois. Dans l'exemple de l'OP, ce n'est pas du tout un problème, car il est simplifié de ne faire qu'une chose, mais dans mon vrai code, il fait beaucoup plus et peut entraîner la perte de données non souhaitées.

En outre, je devais juste arrêter l'ajax et obtenir une réponse personnalisée, rien de plus. Voici ce que j'ai fait:

1. J'ai changé cela:

smk_remove_post();

à ceci:

add_action('parse_query', 'smk_remove_post');

Il est préférable d’exécuter la fonction ultérieurement lorsque cela est nécessaire dans le cadre d’une action spéciale.

2. Ensuite, j'ai modifié le gestionnaire ajax: j'ai supprimé cette ligne smk_remove_post(); et modifié l'action ajax de wp_ajax_smk_remove_post_ajax en wp_ajax_smk_remove_post:

function smk_remove_post_ajax(){
    wp_die( 'ok' );
}
add_action('wp_ajax_smk_remove_post', 'smk_remove_post_ajax');

3. J'ai renommé la chaîne de requête reaction en action. Changé dans l'URL, et fonction:

4. Enfin modifié le script jQuery. Donc, il utilise le fichier admin-ajax.php et envoie l’url sous forme de données:

url: ajaxurl,
data: _this.attr('href'),

Voici le code final:

Lien:

<a href="http://example.com/?action=smk_remove_post&id=1226&_nonce=7be82cd4a0" class="smk-remove-post">Remove post</a>

PHP code:

function smk_remove_post(){
    if( !empty( $_GET['action'] ) && 'smk_remove_post' == $_GET['action'] && !empty( $_GET['id'] ) ){
        if( current_user_can('edit_others_posts') && !empty($_GET['_nonce']) ){
            if( wp_verify_nonce( esc_html( $_GET['_nonce'] ), 'smk_remove_post' ) ){
                // Delete the post
                wp_delete_post( absint( $_GET['id'] ), true );
            }
        }
    }
}
add_action('parse_query', 'smk_remove_post');

function smk_remove_post_ajax(){
    wp_die( 'ok' );
}
add_action('wp_ajax_smk_remove_post', 'smk_remove_post_ajax');

Javascript:

function smk_remove_post(){
    $('.smk-remove-post').on( 'click', function( event ){
        event.preventDefault();
        var _this = $(this);

        jQuery.ajax({
            type: "GET",
            url: ajaxurl,
            data: _this.attr('href').split('?')[1],
            success: function(response){
                console.log(response); // ok
                _this.text('All great, the post is removed.');
            }
        });
    });
}
smk_remove_post();

Edit: Également une petite mise à jour du code ci-dessus. Pour traiter les chaînes de requête, il est nécessaire de supprimer le chemin du site, sinon cela pourrait créer des problèmes inattendus. J'ai ajouté ceci à data href:

.split('?')[1]
3
Andrei Surdu

Faire un lien comme ça

<a href="http://example.com/?reaction=smk_remove_post&id=1226&_nonce=7be82cd4a0" data-id="1226" data-nonce="7be82cd4a0" class="smk-remove-post">Remove post</a>

Et jQuery

$('.smk-remove-post').on( 'click', function( event ){
    event.preventDefault();
    var _this = $(this);

    var data = {
        'action': 'smk_remove_post_ajax',
        'reaction': 'smk_remove_post',
        'id': _this.data('id'),
        '_nonce': _this.data('nonce')
    };

    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
    jQuery.ajax({
        type: "GET",
        url: ajaxurl,
        data: data,
        success: function(response){
            console.log(response);
            _this.text('All great, the post is removed.');
        }
    });
});

Voir Codex à propos de AJAX dans Plugins . Et dans le Codex, il est dit:

La plupart du temps, vous devriez utiliser wp_die () dans votre fonction de rappel Ajax. Cela permet une meilleure intégration avec WordPress et facilite le test de votre code.

Donc, utilisez wp_die(); au lieu de die();

1
Rene Korss

AJAX n'est pas magique et lorsque vous demandez l'URL X, vous recevrez le même code HTML pour cette URL si vous le faites à partir de la barre d'adresse du navigateur, du lien ou du ajax. Par conséquent, si vous souhaitez une réponse différente, le code HTML que vous ne pouvez pas utiliser la même adresse URL pour la demande ajax que dans le lien.

Wordpress a un "point final" spécial pour gérer la requête ajax - admin-ajax.php et toute requête ajax doit lui être envoyée uniquement, quelque chose comme $.ajax({url:....admin-ajax.php}).

Ensuite, vous devez faire savoir à wordpress ce que vous voulez faire. Pour cela, il existe un paramètre spécial dans la requête nommée action. Ce paramètre identifiera le hook à utiliser côté serveur pour traiter la requête. Cette partie que vous avez bien faite dans votre code.

Vous avez maintenant besoin des paramètres supplémentaires qui identifient quel objet doit être manipulé ou récupéré par l'opération AJAX. Vous pouvez utiliser le lien permanent de la publication, ou l'identifiant de la publication par exemple, mais tout dépend de la complexité de l'opération que vous essayez d'effectuer. Dans votre cas spécifique, je suppose qu'un post-id sera le meilleur paramètre pour transmettre la demande.

Comment envoyer les paramètres? la plupart des gens font une demande POST en faisant AJAX, mais si vous voulez un GET, vous pouvez les transmettre dans le cadre de l'URL (ce qui, je suppose, est exactement ce que jQuery fera pour vous) .

1
Mark Kaplun