Лучший способ завершить запрос WordPress Ajax и почему?

16

Рассматривая обычные запросы WordPress Ajax, подобные этим:

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напрямую только потому, что обработка from 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()et al. быть полезным, если вы отправляете ответ в формате 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
источник
Вы добавили несколько хороших точек зрения. Я обновил тему своими мыслями. Вы можете комментировать, если хотите. @JD
прости
@prosti Спасибо, я добавил параграф о том, когда и почему вы / WordPress могли бы использовать dieвместо wp_die().
JD
Я ценю ваши усилия, однако, я не понимаю, почему ядро ​​WordPress иногда используется, die()а иногда wp_die().
Прости
Спасибо @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 и облегчает тестирование вашего кода.

Tunji
источник
Кодекс, который вы отметили, великолепен, но ядро ​​WordPress не следует ему. Как насчет этого?
прост
3
Все wp_send_json_*функции используют все, wp_send_jsonчто до сих пор вызываетwp_die
Tunji
Но почему, я что-то здесь упускаю. Вы проанализировали эти функции и пришли к выводам?
прости
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.
RRikesh
источник
wp_json_encodeв случае исключения может вернуть false, что в таком случае?
прост
Выдает
Таким образом, вы считаете, что wp_send_json()это лучший способ? Почему?
Прости
@prosti wp_send_json() делает кое-что для нас. Этот вопрос также касается wp_send_json().
RRikesh
Это именно @RRikesh, поэтому я спрашиваю, что ядро ​​WP использует эту функцию. Так почему это? Так лучше?
Прости
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 как можно чаще.

Greeso
источник
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?
Прости
1
К сведению, Javascript не обрабатывает echo. wp_send_json_*использует echoи выходит для вас. Здесь есть путаница между клиентом и сервером.
Брайан Фегтер
@prosti wp_send_json ()
Фейсал Алви,
Спасибо, а в случае, если нам не нужен jsonформат вывода?
прости
1
@prosti, чем вы должны использовать wp_die ($ response), потому что в соответствии с кодексом: функция wp_die () предназначена для выдачи выходных данных непосредственно перед тем, как она умрет, чтобы избежать пустых или тайм-аутовых ответов.
Фейсал Алви,