Il modo migliore per terminare una richiesta Ajax in WordPress e perché?
Considerando le normali richieste Ajax di WordPress come queste:
add_action( 'wp_ajax_merrychristmas_happynewyear', array( $this, 'merrychristmas_happynewyear' ) );
add_action( 'wp_ajax_nopriv_merrychristmas_happynewyear', array( $this, 'merrychristmas_happynewyear' ) );
Qual è il modo migliore per terminare la funzione merrychristmas_happynewyear
tra die()
, die(0)
, wp_die()
, o qualcos'altro e perché?

Usare wp_die()
è la migliore tra queste opzioni.
Come altri hanno notato, ci sono molte ragioni per preferire una funzione specifica di WordPress rispetto alla semplice die
o exit
:
- Consente ad altri plugin di agganciarsi alle azioni chiamate da
wp_die()
. - Permette l'uso di un gestore speciale per l'uscita basato sul contesto (il comportamento di
wp_die()
è personalizzato in base al fatto che la richiesta sia una richiesta Ajax o meno). - Rende possibile testare il tuo codice.
L'ultimo punto è il più importante, motivo per cui ho aggiunto quella nota al Codex. Se vuoi creare test unitari/integrazione per il tuo codice, non sarai in grado di testare una funzione che chiama direttamente exit
o die
. Terminerà lo script, come dovrebbe. Il modo in cui i test di WordPress sono configurati per evitare questo problema (per i callback Ajax per i quali ha test) è agganciarsi alle azioni attivate da wp_die()
e lanciare un'eccezione. Questo permette di catturare l'eccezione all'interno del test e analizzare l'output del callback (se presente).
L'unico caso in cui dovresti usare die
o exit
è se vuoi bypassare qualsiasi gestione speciale da parte di wp_die()
e terminare l'esecuzione immediatamente. Ci sono alcuni punti in cui WordPress fa questo (e altri in cui potrebbe usare direttamente die
perché la gestione da parte di wp_die()
non è importante, o nessuno ha ancora provato a creare test per quel pezzo di codice, quindi è stato trascurato). Ricorda che questo rende anche il tuo codice più difficile da testare, quindi generalmente verrebbe usato solo in codice che comunque non è in un corpo di funzione (come fa WordPress in admin-ajax.php
). Quindi, se la gestione da parte di wp_die()
è specificamente non desiderata, o stai terminando lo script in un certo punto come precauzione (come fa admin-ajax.php
, aspettandosi che di solito un callback Ajax abbia già terminato correttamente), allora potresti considerare di usare direttamente die
.
In termini di wp_die()
vs wp_die( 0 )
, quale usare dipende da cosa gestisce la risposta di quella richiesta Ajax sul front end. Se si aspetta un corpo di risposta particolare, allora devi passare quel messaggio (o intero, in questo caso) a wp_die()
. Se tutto ciò che sta ascoltando è che la risposta abbia successo (codice di risposta 200
o altro), allora non c'è bisogno di passare nulla a wp_die()
. Noterei, però, che terminare con wp_die( 0 )
renderebbe la risposta indistinguibile dalla risposta predefinita di admin-ajax.php
. Quindi terminare con 0
non ti dice se il tuo callback è stato collegato correttamente e ha effettivamente funzionato. Un messaggio diverso sarebbe meglio.
Come sottolineato in altre risposte, troverai spesso utili wp_send_json()
e simili se stai inviando una risposta JSON, che generalmente è una buona idea. Questo è anche superiore a chiamare semplicemente wp_die()
con un codice, perché puoi passare molte più informazioni in un oggetto JSON, se necessario. Usare wp_send_json_success()
e wp_send_json_error()
invierà anche il messaggio di successo/errore in un formato standard che qualsiasi funzione helper Ajax JS fornita da WordPress sarà in grado di capire (come wp.ajax
).
TL;DR: Dovresti probabilmente usare sempre wp_die()
, sia in un callback Ajax che non. Ancora meglio, invia informazioni indietro con wp_send_json()
e simili.

Hai aggiunto alcuni punti di vista interessanti. Ho aggiornato la discussione con i miei pensieri. Puoi commentare se vuoi. @J.D

@prosti Grazie, ho aggiunto un paragrafo su quando e perché tu/WordPress potreste usare die
invece di wp_die()
.

Apprezzo il tuo sforzo, tuttavia, non capisco perché il core di WordPress a volte usi die()
e altre volte wp_die()
.

Grazie @prosti. Per quanto riguarda il motivo per cui WordPress a volte utilizza die()
, in alcuni casi si tratta semplicemente di codice legacy, oppure die()
viene usato per terminare lo script come ultima risorsa quando è accaduto qualcosa di veramente inaspettato e wp_die()
non è stato chiamato. In altri casi, nessuno ha creato test per un pezzo di codice, e la gestione speciale di wp_die()
non è specificamente necessaria, quindi è stata trascurata.

Dal codex AJAX nei Plugin
add_action( 'wp_ajax_my_action', 'my_action_callback' );
function my_action_callback() {
global $wpdb; // questo è il modo per accedere al database
$whatever = intval( $_POST['whatever'] );
$whatever += 10;
echo $whatever;
wp_die(); // è necessario per terminare immediatamente e restituire una risposta corretta
}
Nota l'uso di
wp_die()
, invece didie()
oexit()
. Nella maggior parte dei casi dovresti usarewp_die()
nella tua funzione di callback AJAX. Questo garantisce una migliore integrazione con WordPress e rende più facile testare il tuo codice.

il ccodex che hai notato è ottimo, ma il core di WordPress non lo segue. Che ne pensi?

Tutte le funzioni wp_send_json_*
utilizzano wp_send_json
che continua a chiamare wp_die

Ma perché, mi sfugge qualcosa qui. Hai analizzato queste funzioni e sei arrivato a queste conclusioni?

Puoi anche utilizzare wp_send_json()
descritto nel Codex come invia una risposta JSON a una richiesta AJAX e termina l'esecuzione (die()).
Quindi, se devi restituire un array, ti basta concludere la tua funzione con wp_send_json($array_with_values);
. Non è necessario usare echo
o die
.
Hai inoltre a disposizione due funzioni helper wp_send_json_success()
e wp_send_json_error()
che aggiungono una chiave chiamata success
che sarà rispettivamente true
o false
.
Ad esempio:
$array_val = range( 1,10 );
var_dump( wp_send_json_error( $array_val ) ); # Output: {"success":false,"data":[1,2,3,4,5,6,7,8,9,10]}
echo 'Hey there'; # Non verrà eseguito perché l'esecuzione è già terminata.

wp_json_encode
in caso di un'eccezione potrebbe restituire false, cosa succede in quel caso?

@prosti wp_send_json()
fa alcune cose per noi. Questa domanda tratta anche di wp_send_json()
.

Questo è esattamente il motivo @RRikesh per cui sto chiedendo se il core di WP utilizza quella funzione. Quindi perché questo? È meglio così?

Per utilizzare Ajax in WordPress / WooCommerce la sintassi generale è la seguente:
add_action( 'wp_ajax_my_action', 'my_action_callback' );
add_action( 'wp_ajax_nopriv_my_action', 'my_action_callback' );
function my_action_callback()
{
// il tuo codice va qui
wp_die();
}
Dovresti utilizzare wp_die() alla fine della funzione. Perché WordPress internamente utilizza un filtro durante la funzione wp_die(). Quindi qualsiasi plugin che lavora utilizzando quel filtro potrebbe non funzionare se non includiamo wp_die(). Inoltre die() e altre funzioni terminano immediatamente l'esecuzione PHP senza considerare le funzioni di WordPress che dovrebbero essere prese in considerazione durante la terminazione dell'esecuzione.
Se stai usando wp_send_json() all'interno della tua funzione in questo modo
function my_action_callback()
{
// il tuo codice va qui
wp_send_json();
//wp_die(); non è necessario usare wp_die();
}
Non è necessario usare wp_die() alla fine se includi wp_send_json() all'interno della funzione di callback. Perché WordPress stesso utilizza in modo sicuro la funzione wp_die() all'interno di wp_send_json().

Questo è solo un'aggiunta a quanto detto dagli altri. Il motivo per preferire wp_die
è che il core può attivare azioni lì e i plugin possono completare correttamente operazioni come tracciamento, monitoraggio o caching.
In generale, dovresti sempre preferire una chiamata API del core quando disponibile, poiché molto probabilmente aggiunge del valore (caching, integrazione con plugin o altro) che non otterresti dalla chiamata PHP diretta.

Non accetterò questa risposta, non sarebbe corretto. Volevo solo creare una panoramica e possibili suggerimenti sugli elementi che ritengo importanti:
La definizione principale di wp-die()
File: wp-includes/functions.php
2607: /**
2608: * Interrompe l'esecuzione di WordPress e mostra un messaggio HTML con l'errore.
2609: *
2610: * Questa funzione complementa la funzione `die()` di PHP. La differenza è che
2611: * verrà mostrato HTML all'utente. Si raccomanda di usare questa funzione
2612: * solo quando l'esecuzione non dovrebbe continuare oltre. Non è consigliato
2613: * chiamare questa funzione troppo spesso, e si dovrebbe cercare di gestire il maggior numero
2614: * di errori possibile in modo silenzioso o più elegante.
2615: *
2616: * Come scorciatoia, il codice di risposta HTTP desiderato può essere passato come intero
2617: * al parametro `$title` (verrebbe applicato il titolo predefinito) o al parametro `$args`.
2618: *
2619: * @since 2.0.4
2620: * @since 4.1.0 I parametri `$title` e `$args` sono stati modificati per accettare opzionalmente
2621: * un intero da usare come codice di risposta.
2622: *
2623: * @param string|WP_Error $message Opzionale. Messaggio di errore. Se è un oggetto WP_Error,
2624: * e non è una richiesta Ajax o XML-RPC, verranno usati i messaggi dell'errore.
2625: * Predefinito vuoto.
2626: * @param string|int $title Opzionale. Titolo dell'errore. Se `$message` è un oggetto `WP_Error`,
2627: * i dati dell'errore con la chiave 'title' possono essere usati per specificare il titolo.
2628: * Se `$title` è un intero, allora viene trattato come codice
2629: * di risposta. Predefinito vuoto.
2630: * @param string|array|int $args {
2631: * Opzionale. Argomenti per controllare il comportamento. Se `$args` è un intero, allora viene trattato
2632: * come codice di risposta. Predefinito array vuoto.
2633: *
2634: * @type int $response Il codice di risposta HTTP. Predefinito 200 per richieste Ajax, 500 altrimenti.
2635: * @type bool $back_link Se includere un link per tornare indietro. Predefinito false.
2636: * @type string $text_direction La direzione del testo. Questo è utile solo internamente, quando WordPress
2637: * si sta ancora caricando e la locale del sito non è ancora impostata. Accetta 'rtl'.
2638: * Predefinito è il valore di is_rtl().
2639: * }
2640: */
2641: function wp_die( $message = '', $title = '', $args = array() ) {
2642:
2643: if ( is_int( $args ) ) {
2644: $args = array( 'response' => $args );
2645: } elseif ( is_int( $title ) ) {
2646: $args = array( 'response' => $title );
2647: $title = '';
2648: }
2649:
2650: if ( wp_doing_ajax() ) {
2651: /**
2652: * Filtro per il callback che interrompe l'esecuzione di WordPress per richieste Ajax.
2653: *
2654: * @since 3.4.0
2655: *
2656: * @param callable $function Nome della funzione di callback.
2657: */
2658: $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
2659: } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
2660: /**
2661: * Filtro per il callback che interrompe l'esecuzione di WordPress per richieste XML-RPC.
2662: *
2663: * @since 3.4.0
2664: *
2665: * @param callable $function Nome della funzione di callback.
2666: */
2667: $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
2668: } else {
2669: /**
2670: * Filtro per il callback che interrompe l'esecuzione di WordPress per tutte le richieste non-Ajax, non-XML-RPC.
2671: *
2672: * @since 3.0.0
2673: *
2674: * @param callable $function Nome della funzione di callback.
2675: */
2676: $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
2677: }
2678:
2679: call_user_func( $function, $message, $title, $args );
2680: }
wp_send_json
File: wp-includes/functions.php
3144: /**
3145: * Invia una risposta JSON a una richiesta Ajax.
3146: *
3147: * @since 3.5.0
3148: * @since 4.7.0 È stato aggiunto il parametro `$status_code`.
3149: *
3150: * @param mixed $response Variabile (solitamente un array o un oggetto) da codificare come JSON,
3151: * poi stampare e terminare.
3152: * @param int $status_code Il codice di stato HTTP da restituire.
3153: */
3154: function wp_send_json( $response, $status_code = null ) {
3155: @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
3156: if ( null !== $status_code ) {
3157: status_header( $status_code );
3158: }
3159: echo wp_json_encode( $response );
3160:
3161: if ( wp_doing_ajax() ) {
3162: wp_die( '', '', array(
3163: 'response' => null,
3164: ) );
3165: } else {
3166: die;
3167: }
3168: }
wp_doing_ajax
File: wp-includes/load.php
1044: /**
1045: * Determina se la richiesta corrente è una richiesta Ajax di WordPress.
1046: *
1047: * @since 4.7.0
1048: *
1049: * @return bool True se è una richiesta Ajax di WordPress, false altrimenti.
1050: */
1051: function wp_doing_ajax() {
1052: /**
1053: * Filtra se la richiesta corrente è una richiesta Ajax di WordPress.
1054: *
1055: * @since 4.7.0
1056: *
1057: * @param bool $wp_doing_ajax Se la richiesta corrente è una richiesta Ajax di WordPress.
1058: */
1059: return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
1060: }
Tipicamente ciò che otteniamo da una chiamata ajax è una sorta di risposta. La risposta può essere codificata in json o non esserlo.
Nel caso in cui abbiamo bisogno di un output json
, wp_send_json
o i due satelliti sono un'ottima idea.
Tuttavia, potremmo restituire x-www-form-urlencoded
o multipart/form-data
o text/xml
o qualsiasi altro tipo di codifica. In quel caso non usiamo wp_send_json
.
Potremmo restituire l'intero html e in quel caso ha senso usare il primo e il secondo parametro di wp_die()
, altrimenti questi parametri dovrebbero essere vuoti.
wp_die( '', '', array(
'response' => null,
) );
Ma qual è il vantaggio di chiamare wp_die()
senza parametri?
Infine, se controlli il grande core di WP potresti trovare
File: wp-includes/class-wp-ajax-response.php
139: /**
140: * Mostra risposte formattate in XML.
141: *
142: * Imposta l'header del content type a text/xml.
143: *
144: * @since 2.1.0
145: */
146: public function send() {
147: header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) );
148: echo "<?xml version='1.0' encoding='" . get_option( 'blog_charset' ) . "' standalone='yes'?><wp_ajax>";
149: foreach ( (array) $this->responses as $response )
150: echo $response;
151: echo '</wp_ajax>';
152: if ( wp_doing_ajax() )
153: wp_die();
154: else
155: die();
Entrambi i formati sono usati die()
e wp_die()
. Puoi spiegare perché?
Infine ecco cosa restituisce admin-ajax.php
: die( '0' );
Perché non wp_die(...)
?

Se utilizzi echo
, sarai costretto a usare die()
o die(0)
oppure wp_die()
.
Se non usi echo
, JavaScript può gestirlo.
Quindi dovresti usare un modo migliore per restituire i dati: wp_send_json()
.
Per inviare dati nella tua callback (in formato json
), puoi usare i seguenti metodi:
wp_send_json()
wp_send_json_success()
wp_send_json_error()
Tutti questi metodi termineranno l'esecuzione per te. Non sarà necessario usare exit o die in seguito.
AGGIORNAMENTO
E se non hai bisogno del formato json
come output, dovresti usare:
wp_die($response)
Restituirà la tua risposta prima di terminare. Come riportato nel codex:
La funzione
wp_die()
è progettata per fornire un output appena prima di terminare per evitare risposte vuote o timeout.
Leggi l'articolo completo del codex qui.

Da notare che Javascript non gestisce echo
. wp_send_json_*
utilizza echo
e termina per te. C'è confusione qui tra client e server.

Grazie, e nel caso in cui non avessimo bisogno del formato json
come output?

@prosti allora dovresti usare wp_die($response) perché, come riportato nel codex: La funzione wp_die() è progettata per fornire un output appena prima di terminare, evitando così risposte vuote o timeout.

Grazie, @FaisalAlvi per favore [modifica] la tua risposta per renderla più attraente per i voti positivi. Non lasciare dettagli importanti nei commenti.

@prosti Grazie. Ho appena aggiornato la risposta.
