Non riesco a ottenere un oggetto JSON come risposta a una richiesta Ajax con wp_ajax
Ho un problema con WordPress e Ajax.
Questa è la mia parte JavaScript (l'ho ridotta un po'):
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) );
});
Il mio codice PHP è il seguente:
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' );
Lo script ottiene la risposta Ajax da admin-ajax. Sfortunatamente la console genera un errore quando arriva all'istruzione each
nel codice JavaScript... dice:
"Uncaught TypeError: Cannot use 'in' operator to search for '4' in Array".
Se faccio un console.log della mia variabile "posts" ottengo una stringa 'Array'. Non importa come passo la variabile $list
in PHP, restituirà sempre una stringa. La query restituisce post altrove, quindi non è vuota. Ho provato senza json_encode
, con e senza dichiarazione dell'header, usando wp_send_json()
, mettendo ob_clean()
prima di fare l'echo dell'array, mettendo l'array dentro un altro array... Ma viene sempre ricevuto in ajax
come una stringa Array
e each
non può ciclare attraverso di essa.
Questa dovrebbe essere una cosa molto semplice e non riesco a capire perché non funziona. Non ho altri errori o avvisi JavaScript o PHP e tutto il resto funziona correttamente.

La risposta di BODA82 ha aiutato, ma alla fine ho capito che avrei dovuto sostituire il metodo responseText
con responseJSON
nel mio codice JavaScript. Nell'esempio seguente stavo memorizzando i risultati della risposta Ajax in una variabile. Non sapevo che esistesse un metodo specifico per ottenere la risposta in JSON. In questo modo l'oggetto/array con i risultati di get_posts()
viene restituito correttamente e non come una stringa:
posts = $.ajax({
type: 'GET',
url: ajaxurl,
async: false,
dataType: 'json',
data: { action : 'getHotelsList' },
done: function(results) {
// Uhm, forse non ho nemmeno bisogno di questo?
JSON.parse(results);
return results;
},
fail: function( jqXHR, textStatus, errorThrown ) {
console.log( 'Impossibile ottenere i post, risposta del server: ' + textStatus + ': ' + errorThrown );
}
}).responseJSON; // <-- questo invece di .responseText
Nota per me stesso, ma anche consiglio generale: se non riesci a risolvere qualcosa la sera è un segno che dovresti andare a letto, leggere un libro e contare le stelle. Una risposta si troverà la mattina seguente, quanto prima meglio :D

Ci siamo quasi con la tua funzione PHP. Non è necessario impostare l'header. (Modifica: Inoltre, assumendo che get_posts()
stia effettivamente restituendo risultati.)
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 il tuo 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.');
}
});
