No puedo obtener un objeto JSON en respuesta a una solicitud Ajax con wp_ajax

17 nov 2014, 21:40:47
Vistas: 309K
Votos: 6

Tengo un problema con WordPress y Ajax.

Esta es mi parte de JavaScript (la 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 desde admin-ajax. Desafortunadamente, la consola arroja un error cuando llega a la instrucción each en el código JavaScript... dice:

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

Si hago un console.log de mi variable "posts" obtengo un string 'Array'. No importa cómo pase la variable $list en PHP, siempre devolverá una cadena. La consulta devuelve posts en otras partes, así que no está vacía. Intenté sin json_encode, con y sin declarar el encabezado, usando wp_send_json(), poniendo ob_clean() antes de mostrar el array, poniendo el array dentro de otro array... Pero siempre llega a ajax como una cadena Array y each no puede recorrerlo.

Esto debería ser algo muy simple y no puedo entender por qué no está funcionando. No tengo otros errores o advertencias de JavaScript o PHP y todo lo demás funciona bien.

3
Comentarios

¿Qué ves cuando vas a http://www.example.com/wp-admin/admin-ajax.php?action=myAjaxFunc

czerspalace czerspalace
17 nov 2014 22:09:37

¿Algún progreso en tu pregunta? ¿Podrías darle seguimiento por favor?

kaiser kaiser
15 abr 2015 14:27:11

oh... esto es de hace 5 meses... De hecho, respondí a mi propia pregunta al día siguiente de publicarla, utilizando partes de la respuesta de BODA82 - simplemente no la marqué como la respuesta correcta; @toscho añadió su seguimiento mucho más tarde ayer y no puedo verificar si su respuesta también es buena ahora, aunque tiene sentido

unfulvio unfulvio
17 abr 2015 00:13:46
Todas las respuestas a la pregunta 3
0

La respuesta de BODA82 ayudó, pero eventualmente 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 la respuesta en JSON. De esta manera, el objeto/array con los resultados de get_posts() se devuelve correctamente y no como una cadena de texto:

posts = $.ajax({
    type: 'GET',
    url: ajaxurl,
    async: false,
    dataType: 'json',
    data: { action : 'getHotelsList' },
    done: function(results) {
        // Mmm, ¿quizás ni siquiera necesito esto?
        JSON.parse(results);
        return results;
    },
    fail: function( jqXHR, textStatus, errorThrown ) {
        console.log( 'No se pudieron obtener las publicaciones, respuesta del servidor: ' + textStatus + ': ' + errorThrown );
    }
   }).responseJSON; // <-- esto en lugar de .responseText

Nota para mí mismo, pero también un consejo general: si no puedes arreglar algo por la noche, es señal de que deberías irte a la cama, leer un libro y contar estrellas. La respuesta se encontrará a la mañana siguiente, mientras más temprano, mejor :D

18 nov 2014 03:50:51
1

Casi listo con tu función PHP. No es necesario establecer el encabezado. (Edición: También, asumiendo que get_posts() realmente está devolviendo resultados.)

function myAjaxFunc() {

    $posts = get_posts( array(
        'posts_per_page'   => -1,        // Obtener todos los posts
        'orderby'          => 'title',    // Ordenar por título
        'order'            => 'ASC',      // Orden ascendente
        'post_type'        => 'my-post-type', // Tipo de post personalizado
        'post_status'      => array( 'publish', 'draft' ) // Estados de publicación
    ) );

    $list = array();
    foreach ( $posts as $post ) {
        $list[] = array(
            'id'   => $post->ID,          // ID del post
            'name' => $post->post_title,   // Título del post
            'link' => get_permalink( $post->ID ), // Enlace permanente
        );
    }
    echo json_encode( $list );
    die;
}
add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' ); // Para usuarios no logueados
add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' ); // Para usuarios logueados

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('No se pueden recuperar los datos.');
    }
});
17 nov 2014 21:57:17
Comentarios

Cuando guardas algunos datos utilizando JSON.stringify() y luego necesitas leerlos en PHP. El siguiente código funcionó para mí. json_decode( html_entity_decode( stripslashes ($jsonString ) ) );

Vishal Tanna Vishal Tanna
4 dic 2019 09:18:55
0

Hay una solución. Usa complete en lugar de success o done:

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

Y trata de eliminar async:false si el problema persiste.

15 abr 2015 14:15:01