Il modo migliore per terminare una richiesta Ajax in WordPress e perché?

24 dic 2016, 14:18:20
Visualizzazioni: 21.7K
Voti: 24

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é?

0
Tutte le risposte alla domanda 8
4
24

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.

4 feb 2017 23:51:48
Commenti

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

prosti prosti
7 feb 2017 15:12:25

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

J.D. J.D.
7 feb 2017 16:25:55

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

prosti prosti
10 feb 2017 11:27:03

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.

J.D. J.D.
10 feb 2017 15:49:45
5
14

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 di die() o exit(). Nella maggior parte dei casi dovresti usare wp_die() nella tua funzione di callback AJAX. Questo garantisce una migliore integrazione con WordPress e rende più facile testare il tuo codice.

24 dic 2016 14:23:20
Commenti

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

prosti prosti
25 dic 2016 19:23:14

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

Tunji Tunji
25 dic 2016 20:27:25

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

prosti prosti
3 feb 2017 19:02:18

ti dispiacerebbe aggiungere la nota su wp_send_json nella risposta?

Mark Kaplun Mark Kaplun
3 feb 2017 19:18:00

qual è quella corretta? wp_die(0) o wp_die()?

Anwer AR Anwer AR
4 feb 2017 08:01:36
6
10

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.
25 dic 2016 15:31:38
Commenti

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

prosti prosti
25 dic 2016 19:21:26

Genera un'eccezione se il terzo argomento (depth) è minore di 0.

RRikesh RRikesh
26 dic 2016 08:43:44

Quindi ritieni che wp_send_json() sia il modo migliore? Perché?

prosti prosti
3 feb 2017 19:04:16

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

RRikesh RRikesh
4 feb 2017 14:49:48

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

prosti prosti
4 feb 2017 16:03:13

Meno codice mantenendo le cose concise. Lo trovo migliore.

RRikesh RRikesh
4 feb 2017 19:28:44
Mostra i restanti 1 commenti
0

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().

6 feb 2017 09:29:51
0

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.

3 feb 2017 19:24:53
0

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(...)?

7 feb 2017 15:07:25
0

Usa wp_die(). È meglio utilizzare le funzioni di WordPress il più possibile.

5 feb 2017 00:05:53
7

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.

9 feb 2017 16:26:39
Commenti

Grazie, cosa suggerisci invece di echo?

prosti prosti
9 feb 2017 17:12:59

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

Brian Fegter Brian Fegter
9 feb 2017 17:58:13

@prosti wp_send_json()

Faisal Alvi Faisal Alvi
9 feb 2017 18:43:09

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

prosti prosti
9 feb 2017 18:46:59

@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.

Faisal Alvi Faisal Alvi
9 feb 2017 18:59:39

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

prosti prosti
9 feb 2017 19:24:31

@prosti Grazie. Ho appena aggiornato la risposta.

Faisal Alvi Faisal Alvi
9 feb 2017 19:33:28
Mostra i restanti 2 commenti