No se puede obtener un objeto JSON en respuesta a una solicitud ajax con wp_ajax

2

Tengo un problema con WordPress y ajax.

Esta es mi parte de javascript (lo recorté un poco):

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) );
});

Mi código PHP es el siguiente:

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' );

El script obtiene la respuesta ajax de admin-ajax. Desafortunadamente, la consola arroja un error cuando llega a la declaración each en javascript ... dice:

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

Si hago un console.log de mis "posts" var obtengo una cadena 'Array'. No importa cómo pase la variable $list en PHP, siempre devolverá una cadena. La consulta devuelve publicaciones en otros lugares, por lo que no está vacía. Intenté sin json_encode , con y sin declarar encabezado, usando wp_send_json() , poniendo ob_clean() antes de repetir la matriz, colocando la matriz en una matriz ... Pero siempre entra en ajax como una cadena Array y each no puede realizar un ciclo a través de él.

Esto debería ser una cosa muy simple y no puedo entender por qué no funciona. No tengo otros errores o advertencias de javascript o php y todo lo demás funciona bien. Lo llamo un día y me duermo mientras publico esto en la pila :)

    
pregunta unfulvio 17.11.2014 - 20:40

3 respuestas

5
La respuesta de

@ BODA82 ayudó, pero al final me di cuenta de que debería haber reemplazado responseText con el método responseJSON en mi código javascript. En el ejemplo a continuación, estaba almacenando los resultados de la respuesta ajax en una variable. No sabía que existía un método específico para obtener respuesta en JSON. De tal manera, el objeto / matriz con get_posts() resultados se devuelve correctamente y no como una cadena:

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

Nota personal, pero también consejos generales: si no puedes arreglar algo por la noche, es una señal de que debes ir a la cama, leer un libro, contar estrellas. La respuesta se encontrará a la mañana siguiente, cuanto antes mejor: D

    
respondido por el unfulvio 18.11.2014 - 02:50
2

Casi allí con su función PHP. No es necesario configurar el encabezado. (Edición: también, suponiendo que get_posts() en realidad está devolviendo resultados).

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' );

Y tu 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.');
    }
});
    
respondido por el BODA82 17.11.2014 - 20:57
2

Hay una salida, usar completo en lugar de éxito o hecho

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

e intenta eliminar async:false si el problema persiste

    
respondido por el Robot Boy 15.04.2015 - 13:15

Lea otras preguntas en las etiquetas