Melhor maneira de finalizar a solicitação de ajax do WordPress e por quê?

16

Considerando solicitações regulares de ajax do WordPress como estas:

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

Será que vai ser melhor para a função final merrychristmas_happynewyearcom die(), die(0), wp_die(), ou algo mais e por quê?

prosti
fonte

Respostas:

13

Usar wp_die()é a melhor dessas opções.

Como outros observaram, há muitas razões para preferir uma função específica do WordPress em vez da planície dieou exit:

  • Ele permite que outros plugins se conectem às ações chamadas por wp_die().
  • Ele permite que um manipulador especial de saída seja usado com base no contexto (o comportamento de wp_die()é adaptado com base no fato de a solicitação ser uma solicitação Ajax ou não).
  • Torna possível testar seu código.

O último é mais importante, e foi por isso que adicionei essa nota ao Codex . Se você deseja criar testes de unidade / integração para o seu código, não poderá testar uma função que chame exitou diediretamente. Ele encerrará o script, como deveria. A maneira como os próprios testes do WordPress são configurados para evitar isso (para os retornos de chamada do Ajax para os quais ele tem testes), é conectar-se às ações acionadas por wp_die()e lançar uma exceção. Isso permite que a exceção seja capturada no teste e a saída do retorno de chamada (se houver) seja analisada.

A única vez que você usaria dieou exitserá se deseja ignorar qualquer tratamento especial wp_die()e interromper a execução imediatamente. Em alguns lugares, o WordPress faz isso (e em outros locais em que ele pode ser usado diediretamente, apenas porque o manuseio wp_die()não é importante ou porque ninguém tentou criar testes para um pedaço de código ainda, por isso foi ignorado). Lembre-se de que isso também torna seu código mais difícil de testar, por isso geralmente seria usado apenas em códigos que não estão no corpo de uma função (como o WordPress faz admin-ajax.php). Portanto, se o tratamento de wp_die()não for especificamente desejado, ou você estiver matando o script em um determinado momento como uma precaução (comoadmin-ajax.php, esperando que normalmente um retorno de chamada do Ajax já tenha saído corretamente), considere usar diediretamente.

Em termos de wp_die()vs wp_die( 0 ), o que você deve usar depende do que está lidando com a resposta dessa solicitação do Ajax no front-end. Se estiver esperando um corpo de resposta específico, será necessário passar essa mensagem (ou número inteiro, neste caso) para wp_die(). Se tudo o que está ouvindo é que a resposta está sendo bem-sucedida ( 200código de resposta ou o que for), não há necessidade de passar nada wp_die(). Eu observaria, porém, que terminar com wp_die( 0 )tornaria a resposta indistinguível da admin-ajax.phpresposta padrão . Portanto, terminar com 0não informa se o retorno de chamada foi conectado corretamente e realmente executado. Uma mensagem diferente seria melhor.

Como apontado em outras respostas, você encontrará frequentemente wp_send_json()et al. para ser útil se você estiver enviando uma resposta JSON de volta, o que geralmente é uma boa ideia. Isso também é superior a apenas chamar wp_die()com um código, porque você pode passar muito mais informações de volta em um objeto JSON, se necessário. Usar wp_send_json_success()e wp_send_json_error()também enviará a mensagem de sucesso / erro de volta em um formato padrão que qualquer função auxiliar do JS Ajax fornecida pelo WordPress poderá entender (como wp.ajax).

TL; DR: você provavelmente sempre deve usar wp_die(), seja em um retorno de chamada do Ajax ou não. Melhor ainda, envie informações de volta com seus wp_send_json()amigos.

JD
fonte
Você adicionou alguns bons pontos de vista. Eu atualizei o tópico com meus pensamentos. Você pode comentar se quiser. @JD
Prosti
@prosti Obrigado, adicionei um parágrafo sobre quando e por que você / WordPress pode usar em dievez de wp_die().
JD
Agradeço seu esforço, no entanto, não entendo por que o núcleo do WordPress às ​​vezes é usado die()e outras wp_die().
Prosti
Obrigado @prosti. Quanto ao motivo pelo qual o WordPress às ​​vezes usa die(), em alguns casos, é apenas um código legado ou die()está sendo usado para matar o script como último recurso quando algo realmente inesperado aconteceu e wp_die()não foi chamado. Em outros casos, ninguém criou testes para um pedaço de código, e o tratamento especial de wp_die()não é especificamente necessário, por isso foi ignorado.
JD
13

Do codex AJAX em Plugins

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
}

Observe o uso de wp_die(), em vez de die()ou exit(). Na maioria das vezes você deve usar wp_die()sua função de retorno de chamada Ajax. Isso fornece uma melhor integração com o WordPress e facilita o teste do seu código.

Tunji
fonte
o ccodex que você anotou é ótimo, mas o núcleo do WordPress não o segue. Que tal isso?
Prosti
3
Todas as wp_send_json_*funções que todos usam wp_send_jsonque ainda chamamwp_die
Tunji
Mas por que, estou perdendo alguma coisa aqui. Você analisou essas funções e chegou às conclusões?
Prosti
1
você gostaria de adicionar a nota wp_send_jsonna resposta?
Mark Kaplun
1
qual é correto? wp_die (0) ou wp_die ()?
Anwer AR
5

Você também pode usar wp_send_json()descrito no Codex comosend a JSON response back to an AJAX request, and die().

Portanto, se você tiver que retornar uma matriz, terá apenas sua função finalizada wp_send_json($array_with_values);. Não há necessidade echoou die.

Você também recebe duas funções auxiliares de ajuda wp_send_json_success()e wp_send_json_error()que adiciona uma chave denominada successqual será trueou falserespectivamente.

Por exemplo:

$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
fonte
wp_json_encodeno caso de uma exceção pode retornar false, o que nesse caso?
Prosti
Ele lança uma exceção se o terceiro argumento (profundidade) for menor que 0. #
RRikesh 26/16/16
Então você acredita que wp_send_json()é o melhor caminho? Por quê?
Prosti
@prosti wp_send_json() faz algumas coisas para nós. Esta questão também lida com wp_send_json().
precisa saber é o seguinte
É exatamente @RRikesh que estou perguntando ao núcleo do WP que usa essa função. Então, por que isso? É melhor assim?
Prosti
3

Para usar o wordpress ajax / woo commerce, a sintaxe geral do ajax é a seguinte:

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

}

Você deve usar wp_die () no final da função, porque o wordpress usa internamente um filtro durante a função wp_die (). Portanto, qualquer plug-in que esteja trabalhando com esse filtro poderá não funcionar se não incluirmos o wp_die (). Também die () e outras funções matam imediatamente a execução do PHP sem considerar nenhuma função wordpress que deva ser considerada ao finalizar a execução.

Se você estiver usando wp_send_json () dentro de você, funcionará assim

       function my_action_callback()
    {
    // your code goes here

      wp_send_json();

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

    }

Não é necessário usar wp_die () no final se você incluir wp_send_json () dentro da função de retorno de chamada . porque o próprio wordpress usa a função wp_die () com segurança dentro da função wp_send_json ().

Saran
fonte
2

Isso é apenas um acréscimo ao que os outros disseram. O motivo para preferir wp_dieé que o núcleo pode acionar ações lá e os plug-ins podem concluir corretamente coisas como rastreamento, monitoramento ou armazenamento em cache.

Em geral, você sempre deve preferir uma chamada principal da API, se disponível, pois provavelmente adicionará algum valor (cache, integração de plugins ou qualquer outro) que você não obtém da chamada direta do PHP.

Mark Kaplun
fonte
2

Não vou aceitar esta resposta, isso não seria justo. Eu só queria criar um esboço e possíveis dicas sobre os itens que considero importantes:

A principal definição de 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: }

Normalmente, o que recebemos da chamada ajax é algum tipo de resposta. A resposta pode ser codificada em json ou não pode ser codificada em json.

Caso necessitemos de jsoninterrupção wp_send_jsonou dois satélites são uma ótima idéia.

No entanto, podemos voltar x-www-form-urlencodedou multipart/form-dataou text/xmlou qualquer outro tipo de codificação. Nesse caso, não usamos wp_send_json.

Podemos retornar o html inteiro e, nesse caso, faz sentido usar o wp_die()primeiro e o segundo parâmetro, caso contrário, esses parâmetros devem estar vazios.

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

Mas qual é o benefício de chamar wp_die()sem parâmetros?


Por fim, se você verificar o excelente núcleo do WP, poderá encontrar

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

Ambos os formatos são usados die()e wp_die(). Você pode explicar o porquê?

Finalmente, aqui está o que admin-ajax.phpretornadie( '0' );

Por que não wp_die(...)?

prosti
fonte
1

Use wp_die(). É melhor usar as funções do WordPress o máximo possível.

Greeso
fonte
1

Se você usar echo, forçará você a usar die()ou die(0)ou wp_die().

Se você não usar echo, o JavaScript poderá lidar com isso.

Então você deve usar um caminho melhor para retornar dados: wp_send_json().

Para enviar dados em seu retorno de chamada (em jsonformato), você pode usar os seguintes itens:

wp_send_json()

wp_send_json_success()

wp_send_json_error()

Todos eles vão morrer por você. Não há necessidade de sair ou morrer depois.

ATUALIZAR

E se você não precisa jsoncomo formato de saída, deve usar:

wp_die($response)

Ele retornará sua resposta antes que morra. Conforme o codex:

A função wp_die()foi projetada para fornecer saída imediatamente antes de morrer, para evitar respostas vazias ou com tempo limite.

Leia o artigo completo do codex aqui .

Faisal Alvi
fonte
1
Obrigado, o que você sugere em vez de echo?
Prosti
1
Para observar, o Javascript não suporta echo. wp_send_json_*usa echoe sai para você. Aqui há confusão entre o cliente e o servidor.
Brian Fegter 9/02
@prosti wp_send_json ()
Faisal Alvi
Obrigado, e no caso de não precisarmos jsoncomo formato de saída?
Prosti
1
@prosti do que você deve usar wp_die ($ response) porque, de acordo com o codex: A função wp_die () é projetada para fornecer saída imediatamente antes de morrer para evitar respostas vazias ou com tempo limite.
Faisal Alvi