Najlepszy sposób na zakończenie żądania WordPress ajax i dlaczego?

16

Biorąc pod uwagę zwykłe żądania WordPress ajax takie jak te:

add_action( 'wp_ajax_merrychristmas_happynewyear', array( $this, 'merrychristmas_happynewyear' ) );
add_action( 'wp_ajax_nopriv_merrychristmas_happynewyear', array( $this, 'merrychristmas_happynewyear' ) );

To będzie najlepiej funkcjonować końcowego merrychristmas_happynewyearz die(), die(0), wp_die(), lub coś innego i dlaczego?

prosti
źródło

Odpowiedzi:

13

Korzystanie wp_die()jest najlepszą z tych opcji.

Jak zauważyli inni, istnieje wiele powodów, aby preferować funkcję specyficzną dla WordPressa zamiast zwykłego dielub exit:

  • Pozwala innym wtyczkom zaczepić się o akcje wywoływane przez wp_die().
  • Pozwala to na użycie specjalnego modułu obsługi wyjścia w oparciu o kontekst (zachowanie wp_die()jest dostosowane do tego, czy żądanie jest żądaniem Ajax, czy nie).
  • Umożliwia przetestowanie kodu.

Ta ostatnia jest ważniejsza, dlatego dodałem tę notatkę do Kodeksu . Jeśli chcesz utworzyć testy jednostkowe / integracyjne dla swojego kodu, nie będziesz mógł przetestować funkcji, która wywołuje exitlub diebezpośrednio. Zakończy skrypt, tak jak powinien. Sposób, w jaki własne testy WordPressa są skonfigurowane, aby tego uniknąć (w przypadku wywołań zwrotnych Ajax, dla których ma testy), polega na dołączeniu do akcji wyzwalanych przez wp_die()i wygenerowaniu wyjątku. Umożliwia to wychwycenie wyjątku w ramach testu i przeanalizowanie wyniku wywołania zwrotnego (jeśli istnieje).

Jedyny czas, który możesz wykorzystać dielub exitjest, jeśli chcesz ominąć jakąkolwiek specjalną obsługę wp_die()i natychmiast zabić wykonanie. Istnieje kilka miejsc, w których WordPress to robi (i inne, w których może korzystać diebezpośrednio, tylko dlatego, że obsługa z wp_die()nie jest ważna lub nikt nie próbował jeszcze utworzyć testu dla fragmentu kodu, więc został pominięty). Pamiętaj, że to również utrudnia testowanie twojego kodu, więc na ogół byłby używany tylko w kodzie, który i tak nie znajduje się w treści funkcji (tak jak robi to WordPress admin-ajax.php). Więc jeśli obsługa z nie wp_die()jest specjalnie pożądana lub zabijasz skrypt w pewnym momencie jako środek ostrożności (npadmin-ajax.phptak, oczekując, że zwykle wywołanie zwrotne Ajax już poprawnie zakończyło pracę), możesz rozważyć użycie diebezpośrednio.

W odniesieniu do wp_die()vs wp_die( 0 ), którego powinieneś użyć, zależy od tego, co obsługuje odpowiedź tego żądania Ajax na interfejsie. Jeśli oczekuje określonej treści odpowiedzi, musisz przekazać tę wiadomość (lub w tym przypadku liczbę całkowitą) do wp_die(). Jeśli wszystko, czego oczekuje, to odpowiedź się powiedzie ( 200kod odpowiedzi lub cokolwiek innego), to nie trzeba przekazywać niczego wp_die(). Chciałbym jednak zauważyć, że zakończenie wp_die( 0 )oznaczałoby, że odpowiedź byłaby nierozróżnialna od admin-ajax.phpodpowiedzi domyślnej . Więc zakończenie 0nie mówi ci, czy Twoje połączenie zwrotne zostało poprawnie podłączone i uruchomione. Inna wiadomość byłaby lepsza.

Jak wskazano w innych odpowiedziach, często znajdziesz wp_send_json()et al. aby być pomocnym, jeśli wysyłasz odpowiedź JSON z powrotem, co jest ogólnie dobrym pomysłem. Jest to również lepsze niż zwykłe wywoływanie wp_die()za pomocą kodu, ponieważ w razie potrzeby można przekazać znacznie więcej informacji w obiekcie JSON. Użycie wp_send_json_success()i wp_send_json_error()spowoduje również odesłanie komunikatu o powodzeniu / błędzie w standardowym formacie, który będzie mógł zrozumieć (lub polubić wp.ajax) wszystkie funkcje pomocnicze JS Ajax dostarczone przez WordPress .

TL; DR: Prawdopodobnie zawsze powinieneś używać wp_die(), czy to w wywołaniu zwrotnym Ajax, czy nie. Co więcej, odeślij informacje z wp_send_json()przyjaciółmi i znajomymi.

JD
źródło
Dodałeś kilka dobrych punktów widzenia. Zaktualizowałem wątek swoimi myślami. Możesz komentować, jeśli chcesz. @JD
prosti
@ Prosti Dzięki, dodałem akapit o tym, kiedy i dlaczego ty / WordPress może użyć diezamiast wp_die().
JD
Doceniam twój wysiłek, jednak nie rozumiem, dlaczego rdzeń WordPress czasami był używany, die()a czasami wp_die().
prosti
Dzięki @prosti. Jeśli chodzi o to, dlaczego WordPress czasami używa die(), w niektórych przypadkach jest to po prostu starszy kod lub die()jest używany do zabicia skryptu w ostateczności, gdy stało się coś naprawdę nieoczekiwanego i wp_die()nie zostało wywołane. W innych przypadkach nikt nie stworzył testów dla fragmentu kodu, a specjalna obsługa z wp_die()nie jest specjalnie potrzebna, więc zostało to pominięte.
JD
13

Z kodeksu AJAX we wtyczkach

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
}

Zwróć uwagę na użycie wp_die()zamiast die()lub exit(). Przez większość czasu powinieneś używać wp_die()swojej funkcji wywołania zwrotnego Ajax. Zapewnia to lepszą integrację z WordPress i ułatwia testowanie kodu.

Tunji
źródło
kodek, który zauważyłeś, jest świetny, ale rdzeń WordPress go nie przestrzega. Co ty na to?
prosti
3
Wszystkie wp_send_json_*funkcje, z wp_send_jsonktórych korzystają wszystkie, które nadal wywołująwp_die
Tunji,
Ale dlaczego coś tu brakuje. Czy przeanalizowałeś te funkcje i wyciągnąłeś wnioski?
prosti
1
czy chcesz dodać notatkę wp_send_jsondo odpowiedzi?
Mark Kaplun
1
który jest poprawny? wp_die (0) czy wp_die ()?
Anwer AR
5

Możesz także użyć wp_send_json()opisanego w Kodeksie jakosend a JSON response back to an AJAX request, and die().

Tak więc, jeśli musisz zwrócić tablicę, kończysz tylko swoją funkcję wp_send_json($array_with_values);. Nie ma potrzeby echoani die.

Można również uzyskać pomoc pomocnik dwie funkcje wp_send_json_success()i wp_send_json_error()które dodaje klucz o nazwie success, która będzie truelub falseodpowiednio.

Na przykład:

$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.
RRikesh
źródło
wp_json_encodeco w przypadku wyjątku może zwrócić wartość false, co w takim przypadku?
prosti
Zgłasza
Więc wierzysz, że wp_send_json()to najlepszy sposób? Dlaczego?
prosti
@prosti wp_send_json() robi dla nas kilka rzeczy . To pytanie dotyczy również wp_send_json().
RRikesh
Właśnie dlatego @RRikesh pytam, czy rdzeń WP używa tej funkcji. Więc dlaczego to? Czy tak jest lepiej?
prosti
3

W przypadku użycia wordpress ajax / woo commerce ajax ogólna składnia jest następująca:

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

}

Powinieneś użyć wp_die () na końcu funkcji, ponieważ wordpress wewnętrznie używa filtra podczas funkcji wp_die (), więc każda wtyczka, która działa z tym filtrem, może nie działać, jeśli nie uwzględnimy wp_die (). Również die () i inne funkcje natychmiast zabijają wykonanie PHP, nie biorąc pod uwagę żadnej funkcji wordpress, którą należy wziąć pod uwagę podczas kończenia wykonywania.

Jeśli używasz wp_send_json () w środku, działaj w ten sposób

       function my_action_callback()
    {
    // your code goes here

      wp_send_json();

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

    }

Nie jest konieczne użycie wp_die () na końcu, jeśli włączysz wp_send_json () do funkcji zwrotnej . ponieważ samo wordpress bezpiecznie używa funkcji wp_die () wewnątrz funkcji wp_send_json ().

Saran
źródło
2

To tylko dodatek do tego, co powiedzieli inni. Powodem tego wp_diejest to, że rdzeń może tam wywoływać działania, a wtyczki mogą poprawnie wykonywać takie czynności, jak śledzenie, monitorowanie lub buforowanie.

Zasadniczo zawsze powinieneś preferować wywołanie interfejsu API, jeśli jest ono dostępne, ponieważ najprawdopodobniej dodaje ono pewnej wartości (buforowanie, integracja wtyczek itp.), Której nie otrzymujesz z bezpośredniego wywołania PHP.

Mark Kaplun
źródło
2

Nie zaakceptuję tej odpowiedzi, byłoby to niesprawiedliwe. Chciałem tylko stworzyć zarys i możliwe wskazówki na temat elementów, które uważam za ważne:

Główna definicja 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: }

Zazwyczaj to, co otrzymujemy z wywołania ajax, jest pewnego rodzaju odpowiedzią. Odpowiedź może być zakodowana w formacie json lub może nie być zakodowana w formacie json.

Na wypadek, gdybyśmy potrzebowali jsonoutupt wp_send_jsonlub dwóch satelitów, to świetny pomysł.

Jednak możemy powrócić x-www-form-urlencodedlub multipart/form-datalub text/xmllub dowolny inny typ kodowania. W takim przypadku nie korzystamy wp_send_json.

Możemy zwrócić cały HTML i w takim przypadku warto użyć wp_die()pierwszego i drugiego parametru, w przeciwnym razie parametry te powinny być puste.

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

Ale jaka jest korzyść z dzwonienia wp_die()bez parametrów?


Wreszcie, jeśli sprawdzisz świetny rdzeń WP, możesz go znaleźć

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

Oba formaty są używane die()i wp_die(). Czy możesz mi wytłumaczyć dlaczego?

Wreszcie oto, co admin-ajax.phppowracadie( '0' );

Dlaczego nie wp_die(...)?

prosti
źródło
1

Zastosowanie wp_die(). Lepiej jest korzystać z funkcji WordPress jak najwięcej.

Greeso
źródło
1

Jeśli użyjesz echo, zmusi cię do użycia die()lub die(0)lub wp_die().

Jeśli nie używasz echo, JavaScript może to obsłużyć.

Następnie należy użyć lepszego sposobu powrotu dane: wp_send_json().

Aby wysłać dane w oddzwanianiu (w jsonformacie), możesz użyć następujących czynności:

wp_send_json()

wp_send_json_success()

wp_send_json_error()

Wszyscy umrą za ciebie. Nie musisz potem wychodzić ani umrzeć.

AKTUALIZACJA

A jeśli nie potrzebujesz jsonjako formatu wyjściowego, powinieneś użyć:

wp_die($response)

Zwróci twoją odpowiedź, zanim umrze. Zgodnie z kodeksem:

Ta funkcja wp_die()została zaprojektowana tak, aby dawać wyjście tuż przed śmiercią, aby uniknąć pustych odpowiedzi lub przekroczenia limitu czasu.

Przeczytaj pełny kodeks tutaj .

Faisal Alvi
źródło
1
Dzięki, co sugerujesz zamiast echo?
prosti
1
Uwaga: JavaScript nie obsługuje echo. wp_send_json_*używa echoi wychodzi dla ciebie. Pomiędzy klientem a serwerem panuje zamieszanie.
Brian Fegter
@prosti wp_send_json ()
Faisal Alvi
Dzięki, a jeśli nie potrzebujemy jsonjako formatu wyjściowego?
prosti
1
@prosti, niż powinieneś używać wp_die ($ response), ponieważ zgodnie z kodeksem: Funkcja wp_die () została zaprojektowana tak, aby dawać wyjście tuż przed śmiercią, aby uniknąć pustych odpowiedzi lub przekroczenia limitu czasu.
Faisal Alvi