web-dev-qa-db-fra.com

Impossible d'obtenir un objet JSON en réponse à une demande Ajax avec wp_ajax

J'ai un problème avec WordPress et Ajax.

Ceci est ma partie JavaScript (je l'ai coupé un peu):

var posts = $.ajax({
    type: 'POST',
    url: ajaxurl,
    async: false,
    dataType: 'json',
    data: { action: 'myAjaxFunc' },
    done: function(response) {
        return response;
    }
}).responseText;

$.each(posts, function() {
    $('#someSelect').append( $('<option</option>').text(this.name).val(this.id) );
});

Mon code PHP se présente comme suit:

function myAjaxFunc() {

    $posts = get_posts( array(
        'posts_per_page'   => -1,
        'orderby'          => 'title',
        'order'            => 'ASC',
        'post_type'        => 'my-post-type',
        'post_status'      => array( 'publish', 'draft' )
    ) );

    $list = array();
    foreach ( $posts as $post ) {
        $list[] = array(
            'id'   => $post->ID,
            'name' => $post->post_title,
            'link' => get_permalink( $post->ID ),
        );
    }

    header("Content-type: application/json");
    echo json_encode( $list );
    die;
}
add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' );
add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' );

Le script obtient la réponse Ajax de admin-ajax. Malheureusement, la console génère une erreur lorsqu'elle parvient à l'instruction each dans le code JavaScript ... elle dit:

"Uncaught TypeError: Cannot use 'in' operator to search for '4' in Array".

Si je fais un fichier console.log de mes "posts" var, j'obtiens une chaîne "Array". Peu importe comment je passe la variable $list dans PHP, il retournera toujours une chaîne. La requête renvoie des publications ailleurs, elle n'est donc pas vide. J'ai essayé sans json_encode, avec et sans déclaration d'en-tête, en utilisant wp_send_json(), en mettant ob_clean() avant de faire écho au tableau, de placer le tableau dans un tableau ... Mais il entre toujours dans ajax car la chaîne Array et each ne peut pas le parcourir.

Cela devrait être une chose très simple et je ne comprends pas pourquoi cela ne fonctionne pas. Je n'ai pas d'erreur ou d'avertissement JavaScript ou PHP et tout le reste fonctionne correctement.

2
unfulvio

La réponse de BODA82 m'a aidé, mais j'ai finalement réalisé que j'aurais dû remplacer la méthode responseText par la méthode responseJSON dans mon code JavaScript. Dans l'exemple ci-dessous, je stockais les résultats de la réponse Ajax dans une variable. Je ne savais pas qu'il y avait une méthode spécifique pour obtenir la réponse en JSON. De cette manière, l'objet/tableau avec les résultats get_posts() est renvoyé correctement et non sous forme de chaîne:

posts = $.ajax({
    type: 'GET',
    url: ajaxurl,
    async: false,
    dataType: 'json',
    data: { action : 'getHotelsList' },
    done: function(results) {
        // Uhm, maybe I don't even need this?
        JSON.parse(results);
        return results;
    },
    fail: function( jqXHR, textStatus, errorThrown ) {
        console.log( 'Could not get posts, server response: ' + textStatus + ': ' + errorThrown );
    }
   }).responseJSON; // <-- this instead of .responseText

Note à moi-même, mais aussi conseil général: si vous ne pouvez pas réparer quelque chose le soir, c'est un signe que vous devriez aller vous coucher, lire un livre et compter les étoiles. Une réponse sera trouvée le lendemain matin, le plus tôt sera le mieux: D

5
unfulvio

Il y a un moyen de sortir. Utilisez complete au lieu de success ou done:

posts = $.ajax({
    type: 'GET',
    url: ajaxurl,
    async: false,
    dataType: 'json',
    data: { action : 'getHotelsList' },
    complete: function(results) {

Et essayez de supprimer async:false si le problème persiste.

2
Robot Boy

Presque là avec votre fonction PHP. Pas besoin de définir l'en-tête. (Edit: aussi, en supposant que get_posts() renvoie en fait les résultats.)

function myAjaxFunc() {

    $posts = get_posts( array(
        'posts_per_page'   => -1,
        'orderby'          => 'title',
        'order'            => 'ASC',
        'post_type'        => 'my-post-type',
        'post_status'      => array( 'publish', 'draft' )
    ) );

    $list = array();
    foreach ( $posts as $post ) {
        $list[] = array(
            'id'   => $post->ID,
            'name' => $post->post_title,
            'link' => get_permalink( $post->ID ),
        );
    }
    echo json_encode( $list );
    die;
}
add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' );
add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' );

Et votre javascript:

$.ajax({
    url: "<?php bloginfo('url'); ?>/wp-admin/admin-ajax.php",
    type: "POST",
    data: "action=myAjaxFunc",
    success: function(results) {
        var posts = JSON.parse(results);
        console.log(results);
        $.each(posts, function() {
            $('#someSelect').append( $('<option></option>').text(this.name).val(this.id) );
        });
    },
    error: function() {
        console.log('Cannot retrieve data.');
    }
});
2
BODA82