web-dev-qa-db-ja.com

wp_ajaxを使用したAjaxリクエストへの応答でJSONオブジェクトを取得できません

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

スクリプトは、admin-ajaxからAjax応答を取得します。残念ながら、JavaScriptコードのeachステートメントに到達すると、コンソールはエラーをスローします...

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

「posts」変数のconsole.logを実行すると、文字列「Array」が取得されます。 PHPで$list変数をどのように渡しても、常に文字列を返します。クエリは他の場所に投稿を返すため、空ではありません。 json_encodeなしで、ヘッダーを宣言して、なしで、wp_send_json()を使用して、配列をエコーする前にob_clean()を入れ、配列を配列に入れてみました...しかし、常にajaxは文字列としてArrayおよびeachは循環できません。

これは非常に単純なことで、なぜ機能しないのか理解できません。他のJavaScriptやPHPエラーや警告はありませんが、他のすべては正常に動作します。

4
unfulvio

BODA82の答え は助けになりました、しかし結局私は私のJavaScriptコードでresponseTextresponseJSONメソッドに置き換えるべきであることに気づきました。以下の例では、Ajaxレスポンスの結果を変数に格納していました。 JSONで応答を取得するための特定の方法があることを知りませんでした。このようにして、get_posts()の結果を持つオブジェクト/配列は、文字列としてではなく正しく返されます。

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

あなた自身に注意してください、そしてまた一般的なアドバイス:あなたが夕方に何かを直すことができないならそれはあなたが寝て本を読んで星を数えるべきサインです。答えは翌朝見つけられるでしょう、早ければ早いほど:D

7
unfulvio

解決策があります。 completeまたはsuccessの代わりにdoneを使用します。

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

それでも問題が解決しない場合はasync:falseを削除してみてください。

2
Robot Boy

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('Cannot retrieve data.');
    }
});
2
BODA82