Il modo migliore per terminare la richiesta Ajax di WordPress e perché?


16

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

Sarà meglio alla funzione end merrychristmas_happynewyearcon die(), die(0), wp_die(), o qualcos'altro, e perché?

Risposte:


13

L'utilizzo wp_die()è la migliore di queste opzioni.

Come altri hanno notato, ci sono molti motivi per preferire una funzione specifica di WordPress rispetto alla pianura dieo exit:

  • Permette ad altri plugin di agganciarsi alle azioni chiamate da wp_die().
  • Consente di utilizzare un gestore speciale per l'uscita in base al contesto (il comportamento di wp_die()è personalizzato in base al fatto che la richiesta sia o meno una richiesta Ajax).
  • Permette di testare il tuo codice.

L'ultimo è più importante, motivo per cui ho aggiunto quella nota al Codice . Se si desidera creare test di unità / integrazione per il proprio codice, non sarà possibile testare una funzione che chiama exito diedirettamente. Terminerà la sceneggiatura, come dovrebbe. Il modo in cui i test di WordPress sono impostati per evitarlo (per i callback Ajax per cui ha i test), è quello di agganciarsi alle azioni innescate wp_die()e lanciare un'eccezione. Ciò consente di rilevare l'eccezione all'interno del test e di analizzare l'output del callback (se presente).

L'unica volta che vorresti usare dieo exitè se vuoi bypassare qualsiasi gestione speciale wp_die()e uccidere immediatamente l'esecuzione. Ci sono alcuni posti in cui WordPress lo fa (e altri in cui potrebbe essere utilizzato diedirettamente solo perché la gestione da wp_die()non è importante, o nessuno ha ancora tentato di creare test per un pezzo di codice, quindi è stato trascurato). Ricorda che questo rende anche il tuo codice più difficile da testare, quindi sarebbe generalmente usato solo nel codice che non è in un corpo di funzione (come WordPress fa admin-ajax.php). Quindi, se la gestione da non wp_die()è specificamente desiderata, o stai uccidendo lo script a un certo punto come precauzione (comeadmin-ajax.phpsì, prevedendo che di solito un callback Ajax sia già uscito correttamente), quindi potresti prendere in considerazione l'utilizzo diediretto.

In termini di wp_die()vs wp_die( 0 ), che dovresti usare dipende da cosa sta gestendo la risposta di quella richiesta Ajax sul front-end. Se si aspetta un determinato corpo di risposta, è necessario passare quel messaggio (o intero, in questo caso) a wp_die(). Se tutto ciò che sta ascoltando è che la risposta abbia esito positivo ( 200codice di risposta o altro), non è necessario passare nulla a wp_die(). Vorrei notare, tuttavia, che terminare con wp_die( 0 )renderebbe la risposta indistinguibile dalla admin-ajax.phprisposta predefinita . Quindi terminare con 0non ti dice se il tuo callback è stato collegato correttamente ed effettivamente eseguito. Un messaggio diverso sarebbe meglio.

Come sottolineato in altre risposte, troverai spesso wp_send_json()et al. per essere utile se stai inviando una risposta JSON, che è generalmente una buona idea. Questo è anche superiore alla semplice chiamata wp_die()con un codice, perché è possibile trasferire molte più informazioni in un oggetto JSON, se necessario. L'uso wp_send_json_success()e wp_send_json_error()invierà anche il messaggio di successo / errore in un formato standard che qualsiasi funzione di supporto JS Ajax fornita da WordPress sarà in grado di comprendere (come wp.ajax).

TL; DR: Probabilmente dovresti sempre usare wp_die(), sia in una callback Ajax o no. Ancora meglio, rispedire informazioni con wp_send_json()e amici.


Hai aggiunto alcuni buoni punti di vista. Ho aggiornato il thread con i miei pensieri. Puoi commentare se vuoi. @JD
prosti

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

Apprezzo il tuo sforzo, tuttavia, non capisco perché il core di WordPress a volte è stato usato die()e talvolta wp_die().
prosti,

Grazie @prosti. Per quanto riguarda il motivo per cui WordPress a volte utilizza die(), in alcuni casi è solo un codice legacy o die()viene utilizzato per uccidere lo script come ultima risorsa quando è successo qualcosa di davvero imprevisto e wp_die()non è stato chiamato. In altri casi, nessuno ha creato test per un pezzo di codice e la gestione speciale da wp_die()non è specificamente necessaria, quindi è stata trascurata.
JD

13

Dal codice AJAX in Plugin

add_action( 'wp_ajax_my_action', 'my_action_callback' );

function my_action_callback() {
    global $wpdb; // this is how you get access to the database

    $whatever = intval( $_POST['whatever'] );

    $whatever += 10;

        echo $whatever;

    wp_die(); // this is required to terminate immediately and return a proper response
}

Si noti l'uso di wp_die(), invece di die()o exit(). Il più delle volte dovresti usare la wp_die()tua funzione di callback Ajax. Ciò fornisce una migliore integrazione con WordPress e semplifica il test del codice.


il ccodex che hai notato è fantastico, ma il core di WordPress non lo segue. Che ne dici di quello?
prosti

3
Tutte le wp_send_json_*funzioni usano tutte quelle wp_send_jsonche ancora chiamanowp_die
Tunji il

Ma perché, mi manca qualcosa qui. Hai analizzato queste funzioni e hai tratto le conclusioni?
prosti

1
ti dispiace aggiungere la nota sulla wp_send_jsonrisposta?
Mark Kaplun,

1
che è corretto? wp_die (0) o wp_die ()?
Anwer AR

5

Puoi anche usare wp_send_json()descritto nel Codice comesend a JSON response back to an AJAX request, and die().

Quindi, se devi restituire un array, devi solo terminare la tua funzione con wp_send_json($array_with_values);. Non è necessario echoo die.

Hai anche due funzioni di aiuto wp_send_json_success()e wp_send_json_error()che aggiunge una chiave denominata successche sarà trueo falserispettivamente.

Per 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'; # Not executed because already died.

wp_json_encodein caso di un'eccezione può restituire falso, cosa succede in quel caso?
prosti


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

@prosti wp_send_json() fa alcune cose per noi. Questa domanda riguarda anche wp_send_json().
RRikesh

Questo è esattamente @RRikesh perché sto chiedendo al core WP di usare quella funzione. Allora perché questo? È meglio così?
prosti

3

Per usare wordpress ajax / woo commerce la sintassi generale di ajax è 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()
{
// your code goes here

wp_die();

}

Dovresti usare wp_die () alla fine della funzione. Perché wordpress usa internamente un filtro durante la funzione wp_die (). Quindi qualsiasi plugin che stia usando quel filtro potrebbe non funzionare se non includiamo wp_die (). Inoltre die () e altre funzioni vengono immediatamente interrotte l'esecuzione di PHP senza considerare alcuna funzione wordpress che dovrebbe essere presa in considerazione durante la conclusione dell'esecuzione.

Se stai usando wp_send_json () dentro di te funziona in questo modo

       function my_action_callback()
    {
    // your code goes here

      wp_send_json();

    //wp_die(); not necessary to use wp_die();

    }

Non è necessario utilizzare wp_die () alla fine se si include wp_send_json () all'interno della funzione di callback . perché wordpress stesso usa la funzione wp_die () in modo sicuro all'interno della funzione wp_send_json ().


2

Questo è solo in aggiunta a quello che hanno detto gli altri. La ragione per preferire wp_dieè che il core può innescare azioni lì e i plugin possono completare correttamente cose come traccia, monitoraggio o memorizzazione nella cache.

In generale, dovresti sempre preferire una call API centrale se disponibile, poiché è molto probabile che aggiunga un valore (cache, integrazione plug-in o altro) che non ottieni dalla chiamata PHP diretta.


2

Non accetterò questa risposta, non sarebbe giusto. Volevo solo creare uno schema e possibili suggerimenti sugli elementi che trovo importanti:

La definizione principale di wp-die ()

File: wp-includes/functions.php
2607: /**
2608:  * Kill WordPress execution and display HTML message with error message.
2609:  *
2610:  * This function complements the `die()` PHP function. The difference is that
2611:  * HTML will be displayed to the user. It is recommended to use this function
2612:  * only when the execution should not continue any further. It is not recommended
2613:  * to call this function very often, and try to handle as many errors as possible
2614:  * silently or more gracefully.
2615:  *
2616:  * As a shorthand, the desired HTTP response code may be passed as an integer to
2617:  * the `$title` parameter (the default title would apply) or the `$args` parameter.
2618:  *
2619:  * @since 2.0.4
2620:  * @since 4.1.0 The `$title` and `$args` parameters were changed to optionally accept
2621:  *              an integer to be used as the response code.
2622:  *
2623:  * @param string|WP_Error  $message Optional. Error message. If this is a WP_Error object,
2624:  *                                  and not an Ajax or XML-RPC request, the error's messages are used.
2625:  *                                  Default empty.
2626:  * @param string|int       $title   Optional. Error title. If `$message` is a `WP_Error` object,
2627:  *                                  error data with the key 'title' may be used to specify the title.
2628:  *                                  If `$title` is an integer, then it is treated as the response
2629:  *                                  code. Default empty.
2630:  * @param string|array|int $args {
2631:  *     Optional. Arguments to control behavior. If `$args` is an integer, then it is treated
2632:  *     as the response code. Default empty array.
2633:  *
2634:  *     @type int    $response       The HTTP response code. Default 200 for Ajax requests, 500 otherwise.
2635:  *     @type bool   $back_link      Whether to include a link to go back. Default false.
2636:  *     @type string $text_direction The text direction. This is only useful internally, when WordPress
2637:  *                                  is still loading and the site's locale is not set up yet. Accepts 'rtl'.
2638:  *                                  Default is the value of 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:        * Filters the callback for killing WordPress execution for Ajax requests.
2653:        *
2654:        * @since 3.4.0
2655:        *
2656:        * @param callable $function Callback function name.
2657:        */
2658:       $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
2659:   } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
2660:       /**
2661:        * Filters the callback for killing WordPress execution for XML-RPC requests.
2662:        *
2663:        * @since 3.4.0
2664:        *
2665:        * @param callable $function Callback function name.
2666:        */
2667:       $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
2668:   } else {
2669:       /**
2670:        * Filters the callback for killing WordPress execution for all non-Ajax, non-XML-RPC requests.
2671:        *
2672:        * @since 3.0.0
2673:        *
2674:        * @param callable $function Callback function name.
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:  * Send a JSON response back to an Ajax request.
3146:  *
3147:  * @since 3.5.0
3148:  * @since 4.7.0 The `$status_code` parameter was added.
3149:  *
3150:  * @param mixed $response    Variable (usually an array or object) to encode as JSON,
3151:  *                           then print and die.
3152:  * @param int   $status_code The HTTP status code to output.
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:  * Determines whether the current request is a WordPress Ajax request.
1046:  *
1047:  * @since 4.7.0
1048:  *
1049:  * @return bool True if it's a WordPress Ajax request, false otherwise.
1050:  */
1051: function wp_doing_ajax() {
1052:   /**
1053:    * Filters whether the current request is a WordPress Ajax request.
1054:    *
1055:    * @since 4.7.0
1056:    *
1057:    * @param bool $wp_doing_ajax Whether the current request is a WordPress Ajax request.
1058:    */
1059:   return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
1060: }

In genere ciò che otteniamo dalla chiamata Ajax è una sorta di risposta. La risposta può essere codificata in json o potrebbe non essere codificata in json.

Nel caso in cui abbiamo bisogno di jsonscoppi wp_send_jsono due satelliti sono una grande idea.

Tuttavia, possiamo tornare x-www-form-urlencodedo multipart/form-datao text/xmlo qualsiasi altro tipo di codifica. In quel caso non usiamo wp_send_json.

Potremmo restituire l'intero codice HTML e in tal caso ha senso usare il wp_die()primo e il secondo parametro, altrimenti questi parametri dovrebbero essere vuoti.

 wp_die( '', '', array(
      'response' => null,
 ) );

Ma qual è il vantaggio di chiamare wp_die()senza parametri?


Infine, se controlli l'ottimo core WP che potresti trovare

File: wp-includes/class-wp-ajax-response.php
139:    /**
140:     * Display XML formatted responses.
141:     *
142:     * Sets the content type header to 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 utilizzati die()e wp_die(). Puoi spiegare perché?

Finalmente ecco cosa admin-ajax.phpritornadie( '0' );

Perché no wp_die(...)?


1

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


1

Se lo usi echo, ti costringerà a usare die()o die(0)o wp_die().

Se non lo usi echo, JavaScript può gestirlo.

Poi si dovrebbe usare un modo migliore per restituire i dati: wp_send_json().

Per inviare dati nel callback (in jsonformato), è possibile utilizzare i seguenti:

wp_send_json()

wp_send_json_success()

wp_send_json_error()

Tutti moriranno per te. Non c'è bisogno di uscire o morire dopo.

AGGIORNARE

E se non ti serve jsoncome formato di output, dovresti usare:

wp_die($response)

Restituirà la tua risposta prima che muoia. Secondo il codice:

La funzione wp_die()è progettata per fornire un output appena prima che muoia per evitare risposte vuote o timeout.

Leggi l'articolo completo sul codice qui .


1
Grazie, cosa suggerisci invece di echo?
prosti

1
Da notare, Javascript non gestisce echo. wp_send_json_*usa echoed esce per te. Qui c'è confusione tra client e server.
Brian Fegter,

@prosti wp_send_json ()
Faisal Alvi

Grazie, e nel caso non avessimo bisogno jsoncome formato di output?
prosti

1
@prosti di quanto dovresti usare wp_die ($ response) perché secondo il codice: la funzione wp_die () è progettata per fornire output appena prima che muoia per evitare risposte vuote o timeout.
Faisal Alvi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.