Не могу получить объект JSON в ответе на Ajax-запрос с wp_ajax

17 нояб. 2014 г., 21:40:47
Просмотры: 309K
Голосов: 6

У меня проблема с WordPress и Ajax.

Вот моя часть JavaScript (я немного её сократил):

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

Мой PHP-код выглядит следующим образом:

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

Скрипт получает Ajax-ответ от admin-ajax. К сожалению, консоль выдает ошибку, когда доходит до выражения each в JavaScript коде... в ней говорится:

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

Если я сделаю console.log моей переменной "posts", я получу строку 'Array'. Независимо от того, как я передаю переменную $list в PHP, она всегда возвращает строку. Запрос возвращает записи в других местах, так что он не пустой. Я пробовал без json_encode, с объявлением заголовка и без, используя wp_send_json(), вставляя ob_clean() перед выводом массива, помещая массив в массив... Но он всегда приходит в ajax как строка Array, и each не может перебирать его.

Это должно быть очень простой вещью, и я не могу понять, почему это не работает. У меня нет других ошибок или предупреждений JavaScript или PHP, и всё остальное работает нормально.

3
Комментарии

Что вы видите, когда переходите на http://www.example.com/wp-admin/admin-ajax.php?action=myAjaxFunc

czerspalace czerspalace
17 нояб. 2014 г. 22:09:37

Есть ли прогресс с вашим вопросом? Не могли бы вы, пожалуйста, продолжить обсуждение?

kaiser kaiser
15 апр. 2015 г. 14:27:11

ох... этот вопрос был 5 месяцев назад... Кстати, я сам ответил на свой вопрос на следующий день после публикации, используя части ответа BODA82 - я просто не отметил его как правильный ответ; @toscho добавил свой ответ гораздо позже вчера. Сейчас я не могу проверить, хорош ли его ответ, хотя он имеет смысл

unfulvio unfulvio
17 апр. 2015 г. 00:13:46
Все ответы на вопрос 3
0

Ответ BODA82 помог, но в итоге я понял, что должен был заменить метод responseText на responseJSON в моём JavaScript коде. В примере ниже я сохранял результаты Ajax-ответа в переменную. Я не знал, что существует специальный метод для получения ответа в формате JSON. Таким образом объект/массив с результатами get_posts() возвращается корректно, а не как строка:

posts = $.ajax({
    type: 'GET',
    url: ajaxurl,
    async: false,
    dataType: 'json',
    data: { action : 'getHotelsList' },
    done: function(results) {
        // Хм, возможно это мне даже не нужно?
        JSON.parse(results);
        return results;
    },
    fail: function( jqXHR, textStatus, errorThrown ) {
        console.log( 'Не удалось получить посты, ответ сервера: ' + textStatus + ': ' + errorThrown );
    }
   }).responseJSON; // <-- это вместо .responseText

Заметка для себя, но также общий совет: если вы не можете что-то исправить вечером, это знак, что вам следует лечь спать, почитать книгу и посчитать звёзды. Ответ найдётся на следующее утро, чем раньше, тем лучше :D

18 нояб. 2014 г. 03:50:51
1

Почти готово с вашей PHP-функцией. Нет необходимости устанавливать заголовок. (Примечание: также предполагается, что get_posts() действительно возвращает результаты.)

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

И ваш 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('Не удалось получить данные.');
    }
});
17 нояб. 2014 г. 21:57:17
Комментарии

Когда вы сохраняете данные с помощью JSON.stringify(), а затем вам нужно прочитать их в PHP. Следующий код сработал для меня: json_decode( html_entity_decode( stripslashes ($jsonString ) ) );

Vishal Tanna Vishal Tanna
4 дек. 2019 г. 09:18:55
0

Есть выход. Используйте complete вместо success или done:

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

И попробуйте убрать async:false, если проблема не исчезнет.

15 апр. 2015 г. 14:15:01