Найкращий спосіб завершити запит на ajax WordPress і чому?


16

Розглядаючи звичайні запити ajax WordPress на зразок таких:

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

Чи буде це краще для кінцевого функції merrychristmas_happynewyearз die(), die(0), wp_die()або що - то інше , і чому?

Відповіді:


13

Використання wp_die()є найкращим із цих варіантів.

Як зазначають інші, є багато причин віддати перевагу функції WordPress над рівниною dieабо exit:

  • Це дозволяє іншим плагінам підключитися до дій, які викликаються wp_die().
  • Це дозволяє використовувати спеціальний обробник для виходу на основі контексту (поведінка wp_die()налаштована на основі того, запит є запитом Ajax чи ні).
  • Це дає можливість протестувати ваш код.

Остання важливіша, саме тому я додав цю нотатку до Кодексу . Якщо ви хочете створити блок-тести / інтеграційні тести для свого коду, ви не зможете протестувати функцію, яка викликає exitабо dieбезпосередньо. Він припинить сценарій, як і належить. Спосіб налаштування власних тестів WordPress для уникнення цього (для зворотних викликів Ajax, для яких він має тести), - це підключення до дій, викликаних wp_die()і викинути виняток. Це дозволяє зафіксувати виняток у межах тесту, а вихід зворотного дзвінка (якщо такий є) проаналізувати.

Єдиний час, який ви використовували б, dieабо exitце, якщо ви хочете обійти якусь спеціальну обробку wp_die()та негайно вбити виконання. Є деякі місця, де WordPress робить це (та інші місця, де він може використовуватись dieбезпосередньо лише тому, що керування з wp_die()них не важливо, або ніхто ще не намагався створити тести для фрагмента коду, тому його не помітили). Пам’ятайте, що це також робить ваш код складнішим для тестування, тому він, як правило, використовується лише в коді, який так чи інакше не є функціональним тілом (як це робить WordPress admin-ajax.php). Тож якщо обробка від wp_die()конкретно не бажана, або ви вбиваєте сценарій у певний момент як запобіжна норма (наприкладadmin-ajax.phpтак, очікуючи, що зазвичай зворотний виклик Ajax вже належним чином вийшов), тоді ви можете подумати про використання dieбезпосередньо.

У відношенні wp_die()vs wp_die( 0 ), який ви повинні використовувати, залежить від того, що обробляє відповідь на той запит Ajax на передній частині. Якщо він очікує конкретного органу відповіді, вам потрібно передати це повідомлення (або ціле число, в даному випадку) wp_die(). Якщо все, що він слухає, - це відповідь успішна ( 200код відповіді чи що завгодно), тоді нічого не потрібно передавати wp_die(). Хоча зауважити, що закінчення wp_die( 0 )зробить відповідь невідмінною від відповіді за замовчуванням admin-ajax.php. Отже, закінчення 0не означає, чи правильно було підключено ваш зворотний дзвінок і чи справді він працював. Інше повідомлення було б краще.

Як вказувалося в інших відповідях, ви часто зустрінетесь wp_send_json()та ін. бути корисним, якщо ви надсилаєте відповідь JSON назад, що, як правило, є хорошою ідеєю. Це також чудово, ніж просто виклик wp_die()з кодом, тому що ви можете передати набагато більше інформації назад в об'єкт JSON, якщо потрібно. Використовуючи wp_send_json_success()та wp_send_json_error()також відправляти повідомлення про успіх / помилку назад у стандартному форматі, що будь-які помічники JS Ajax, надані WordPress, зможуть зрозуміти (як wp.ajax).

TL; DR: Напевно, ви завжди повинні користуватися wp_die(), будь то в зворотному дзвінку Ajax чи ні. Ще краще, надсилайте інформацію назад wp_send_json()і друзям.


Ви додали кілька хороших точок зору. Я оновив нитку своїми думками. Ви можете коментувати, якщо вам подобається. @JD
prosti

@prosti Спасибі, я додав абзац про те, коли і чому ви / WordPress можете використовувати dieзамість wp_die().
JD

Я ціную ваші зусилля, проте я не розумію, чому ядро ​​WordPress іноді використовується, die()а іноді wp_die().
prosti

Дякую @prosti. Що стосується того, чому WordPress іноді використовує die(), то в деяких випадках це просто застарілий код, або die()він використовується для вбивства сценарію в крайньому випадку, коли сталося щось дійсно несподіване і wp_die()не викликали. В інших випадках ніхто не створив тести на фрагмент коду, і спеціальна обробка wp_die()не спеціально потрібна, тому її не помітили.
JD

13

З кодексу AJAX у плагінах

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
}

Помітьте використання wp_die()замість die()або exit(). Більшу частину часу вам слід використовувати wp_die()у функції зворотного дзвінка Ajax. Це забезпечує кращу інтеграцію з WordPress та полегшує тестування коду.


кодекс, який ви зазначили, чудовий, але ядро ​​WordPress цього не дотримується. Як про те, що?
prosti

3
Усі wp_send_json_*функції, wp_send_jsonякі все ще використовуютьwp_die
Tunji

Але чому, я щось тут пропускаю. Ви проаналізували ці функції та прийшли до висновків?
prosti

1
Ви не проти додати нотатку про wp_send_jsonвідповідь?
Марк Каплун

1
що правильно? wp_die (0) чи wp_die ()?
Anwer AR

5

Ви також можете використовувати wp_send_json()описаний у Кодексі якsend a JSON response back to an AJAX request, and die().

Отже, якщо вам доведеться повернути масив, ви лише закінчите свою функцію wp_send_json($array_with_values);. Не потрібно echoабо die.

Ви також можете отримати дві довідки допоміжних функцій wp_send_json_success()і wp_send_json_error()який додає ключ з ім'ям , successяке буде trueабо falseвідповідно.

Наприклад:

$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_encodeякщо виняток може повернути помилкове, що в цьому випадку?
prosti

Він викидає виняток, якщо третій аргумент (глибина) менше 0.
RRikesh

Отже, ти вважаєш, що wp_send_json()це найкращий спосіб? Чому?
prosti

@prosti wp_send_json() робить щось для нас. Це питання також стосується wp_send_json().
RRikesh

Це саме @RRikesh, чому я прошу, щоб ядро ​​WP використовує цю функцію. То чому це? Чи краще так?
prosti

3

Для використання wordpress ajax / woo commerce загальний синтаксис ajax такий:

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

}

Ви повинні використовувати wp_die () в кінці функції. Тому що wordpress внутрішньо використовує фільтр під час функції wp_die (). Тому будь-який плагін, який працює за допомогою цього фільтра, може не працювати, якщо ми не включимо wp_die (). Також die () та інші функції негайно вбивають виконання PHP, не враховуючи жодної функції wordpress, яку слід враховувати під час завершення виконання.

Якщо ви використовуєте wp_send_json () всередині, ви працюєте так

       function my_action_callback()
    {
    // your code goes here

      wp_send_json();

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

    }

Не потрібно використовувати wp_die () наприкінці, якщо ви включаєте wp_send_json () у функцію зворотного виклику . тому що сам wordpress безпечно використовує функцію wp_die () у функції wp_send_json ().


2

Це лише на додаток до сказаного іншими. Причина віддати перевагу wp_dieполягає в тому, що ядро ​​може запускати дії там, а плагіни можуть належним чином завершувати такі речі, як відстеження, моніторинг чи кешування.

Загалом, вам завжди слід віддавати перевагу базовому виклику API, якщо такий доступний, оскільки він, швидше за все, додає значення (кешування, інтеграція плагінів чи іншого), яке ви не отримуєте під час прямого виклику PHP.


2

Я не прийму цієї відповіді, це не було б справедливо. Я просто хотів створити контур та можливі підказки щодо предметів, які я вважаю важливими:

Основне визначення 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: }

Як правило, те, що ми отримуємо від дзвінка Ajax, - це якась відповідь. Відповідь може бути закодована в json або не може бути кодована в json.

У випадку, якщо нам потрібен jsonпідсилювач wp_send_jsonабо два супутники - це чудова ідея.

Тим НЕ менше, ми можемо повернути x-www-form-urlencodedабо multipart/form-dataабо text/xmlабо будь-який інший тип кодування. У такому випадку ми не використовуємо wp_send_json.

Ми можемо повернути весь html, і в цьому випадку має сенс використовувати wp_die()перший і другий параметр, інакше ці параметри повинні бути порожніми.

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

Але яка вигода дзвінка wp_die()без параметрів?


Нарешті, якщо ви перевірите чудове ядро ​​WP, яке ви можете знайти

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

Використовуються обидва формати die()і wp_die(). Чи можете ви пояснити, чому?

Нарешті ось що admin-ajax.phpповертаєdie( '0' );

Чому ні wp_die(...)?


1

Використовуйте wp_die(). Краще використовувати функції WordPress скільки завгодно.


1

Якщо ви використовуєте echo, це змусить вас використовувати die()або die(0)або wp_die().

Якщо ви не використовуєте echo, JavaScript може це впоратися.

Потім ви повинні використовувати кращий спосіб повернути дані: wp_send_json().

Щоб надіслати дані у зворотному дзвінку (у jsonформаті), ви можете використовувати наступні дії:

wp_send_json()

wp_send_json_success()

wp_send_json_error()

Усі вони помруть за вас. Не потрібно виходити або вмирати після цього.

ОНОВЛЕННЯ

І якщо вам не потрібен jsonвихідний формат, слід використовувати:

wp_die($response)

Він поверне вашу відповідь до смерті. Відповідно до кодексу:

Функція wp_die()призначена для отримання результатів безпосередньо перед смертю, щоб уникнути порожніх або очікуваних реакцій.

Прочитайте повну статтю про кодекс тут .


1
Спасибі, що ви пропонуєте замість цього echo?
prosti

1
Зауважимо, Javascript не обробляє echo. wp_send_json_*використовує echoта виходить для вас. Тут виникає плутанина між клієнтом і сервером.
Брайан Фегтер

@prosti wp_send_json ()
Faisal Alvi

Дякую, а якщо нам не потрібен jsonвихідний формат?
prosti

1
@prosti, ніж ви повинні використовувати wp_die ($ відповідь), оскільки згідно з кодексом: Функція wp_die () призначена для отримання результатів перед тим, як він вмирає, щоб уникнути порожніх або сповільнених відповідей.
Faisal Alvi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.