Não é possível obter um objeto JSON em resposta a uma solicitação ajax com wp_ajax

2

Eu tenho um problema com o WordPress e o ajax.

Esta é a minha parte javascript (eu aparado um pouco):

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

Meu código PHP é o seguinte:

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

O script obtém a resposta do ajax do admin-ajax. Infelizmente, o console lança um erro quando chega à instrução each em javascript ... ele diz:

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

Se eu fizer um console.log do meu "posts" var eu recebo uma string 'Array'. Não importa como eu passe a variável $list no PHP, ela sempre retornará uma string. A consulta retorna posts em outro lugar, por isso não está vazia. Eu tentei sem json_encode , com e sem declarar header, usando wp_send_json() , colocando ob_clean() antes de ecoar o array, colocando o array em um array ... Mas ele sempre entra em ajax como uma string Array e each não pode passar por ele.

Isso deve ser uma coisa muito simples e não consigo entender por que não está funcionando. Eu não tenho outros erros de javascript ou php ou avisos e tudo mais corre bem. Eu estou chamando por um dia e conseguindo dormir enquanto coloco isso na pilha:)

    
por unfulvio 17.11.2014 / 20:40

3 respostas

5

A resposta do BODA82 ajudou, mas finalmente percebi que deveria ter substituído o método responseText with responseJSON em meu código javascript. No exemplo abaixo, eu estava armazenando os resultados da resposta do ajax em uma variável. Eu não sabia que havia um método específico para obter resposta no JSON. Dessa forma, o objeto / array com get_posts() results é retornado corretamente e não como string:

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 para si mesmo, mas também conselho geral: se você não pode consertar alguma coisa à noite, é um sinal de que deve ir para a cama, ler um livro, contar estrelas. Resposta será encontrada na manhã seguinte, quanto mais cedo melhor: D

    
por unfulvio 18.11.2014 / 02:50
2

Quase lá com sua função PHP. Não há necessidade de definir o cabeçalho. (Edit: Além disso, assumindo que get_posts() está retornando 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' );

E seu 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.');
    }
});
    
por BODA82 17.11.2014 / 20:57
2

Existe uma saída, uso completo em vez de sucesso ou feito

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

e tente remover async:false se o problema persistir

    
por Robot Boy 15.04.2015 / 13:15