La mejor manera de finalizar la solicitud de WordPress ajax y ¿por qué?

16

Considerando las solicitudes regulares de WordPress ajax como estas:

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

¿Será posible para la función final merrychristmas_happynewyearcon die(), die(0), wp_die(), o algo más y por qué?

prosti
fuente

Respuestas:

13

Usar wp_die()es la mejor de esas opciones.

Como otros han señalado, hay muchas razones para preferir una función específica de WordPress sobre la simple dieo exit:

  • Permite que otros complementos se enganchen en las acciones llamadas por wp_die().
  • Permite utilizar un controlador especial para salir en función del contexto (el comportamiento de wp_die()se adapta según si la solicitud es una solicitud de Ajax o no).
  • Permite probar su código.

El último es más importante, por eso agregué esa nota al Codex . Si desea crear pruebas de unidad / integración para su código, no podrá probar una función que llame exito diedirectamente. Terminará el script, como se supone que debe hacerlo. La forma en que las propias pruebas de WordPress están configuradas para evitar esto (para las devoluciones de llamada de Ajax para las que tiene pruebas), es engancharse a las acciones activadas por wp_die()y lanzar una excepción. Esto permite capturar la excepción dentro de la prueba y analizar la salida de la devolución de llamada (si la hay).

El único momento que usaría dieo exites si desea omitir cualquier manejo especial wp_die()y matar la ejecución de inmediato. Hay algunos lugares donde WordPress hace esto (y otros lugares donde podría usar diedirectamente solo porque el manejo wp_die()no es importante, o nadie ha intentado crear pruebas para un fragmento de código todavía, por lo que se pasó por alto). Recuerde que esto también hace que su código sea más difícil de probar, por lo que generalmente solo se usaría en código que no está en un cuerpo de función de todos modos (como lo hace WordPress admin-ajax.php). Entonces, si el manejo desde wp_die()específicamente no se desea, o si está eliminando el script en cierto punto como precaución (comoadmin-ajax.phpsi espera que, por lo general, una devolución de llamada de Ajax ya haya salido correctamente), entonces puede considerar usarlo diedirectamente.

En términos de wp_die()vs wp_die( 0 ), lo que debe usar depende de lo que esté manejando la respuesta de esa solicitud de Ajax en el front-end. Si está esperando un cuerpo de respuesta particular, entonces necesita pasar ese mensaje (o entero, en este caso) a wp_die(). Si todo lo que está escuchando es que la respuesta sea exitosa ( 200código de respuesta o lo que sea), entonces no hay necesidad de pasarle nada wp_die(). Sin embargo, me gustaría señalar que terminar con wp_die( 0 )haría la respuesta indistinguible de la admin-ajax.phprespuesta predeterminada . Por lo tanto, terminar con 0no le dice si su devolución de llamada se conectó correctamente y realmente se ejecutó. Un mensaje diferente sería mejor.

Como se señaló en otras respuestas, a menudo encontrará wp_send_json()et al. ser útil si está enviando una respuesta JSON, lo que generalmente es una buena idea. Esto también es superior a solo llamar wp_die()con un código, porque puede pasar mucha más información de vuelta en un objeto JSON, si es necesario. Usando wp_send_json_success()y wp_send_json_error()también enviará el mensaje de éxito / error en un formato estándar que cualquier función auxiliar JS Ajax proporcionada por WordPress podrá entender (me gusta wp.ajax).

TL; DR: Probablemente siempre debería usar wp_die(), ya sea en una devolución de llamada Ajax o no. Aún mejor, envíe información de regreso con wp_send_json()y amigos.

JD
fuente
Agregaste algunos buenos puntos de vista. Actualicé el hilo con mis pensamientos. Puedes comentar si quieres. @JD
prosti
@prosti Gracias, he agregado un párrafo sobre cuándo y por qué usted / WordPress podría usar en dielugar de wp_die().
JD
Aprecio su esfuerzo, sin embargo, no entiendo por qué el núcleo de WordPress a veces se usa die()y otras wp_die().
prosti
Gracias @prosti. En cuanto a por qué a veces se usa WordPress die(), en algunos casos es solo código heredado, o die()se está utilizando para eliminar el script como último recurso cuando sucedió algo realmente inesperado y wp_die()no se llamó. En otros casos, nadie ha creado pruebas para un fragmento de código, y el manejo especial de wp_die()no es específicamente necesario, por lo que se ha pasado por alto.
JD
13

Desde el codex AJAX en 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 el uso de wp_die(), en lugar de die()o exit(). La mayoría de las veces deberías estar usando wp_die()tu función de devolución de llamada Ajax. Esto proporciona una mejor integración con WordPress y hace que sea más fácil probar su código.

Tunji
fuente
el ccodex que notó es excelente, pero el núcleo de WordPress no lo sigue. ¿Qué hay sobre eso?
prosti
3
Todas las wp_send_json_*funciones que todos usan y wp_send_jsonque aún llamawp_die
Tunji
Pero por qué, me falta algo aquí. ¿Has analizado estas funciones y sacaste las conclusiones?
prosti
1
¿te importaría agregar la nota sobre wp_send_jsonen la respuesta?
Mark Kaplun
1
¿cual es correcta? wp_die (0) o wp_die ()?
Anwer AR
5

También puede usarlo wp_send_json()descrito en el Codex comosend a JSON response back to an AJAX request, and die().

Entonces, si tiene que devolver una matriz, solo tiene que finalizar su función con wp_send_json($array_with_values);. No es necesario echoo die.

También obtienes dos funciones de ayuda de ayuda wp_send_json_success()y wp_send_json_error()que agrega una clave llamada successcual será trueo falserespectivamente.

Por ejemplo:

$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
fuente
wp_json_encodeen caso de una excepción puede devolver falso, ¿qué pasa en ese caso?
prosti
Lanza una excepción si el tercer argumento (profundidad) es menor que 0.
RRikesh
¿Entonces crees que wp_send_json()es la mejor manera? ¿Por qué?
prosti
@prosti wp_send_json() hace algunas cosas por nosotros. Esta pregunta también trata wp_send_json().
RRikesh
Esto es exactamente @RRikesh por lo que le pido al núcleo de WP que use esa función. Entonces, ¿por qué esto? ¿Es mejor así?
prosti
3

Para usar wordpress ajax / woo commerce, la sintaxis general de ajax es la siguiente:

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

}

Debe usar wp_die () al final de la función. Porque wordpress usa internamente un filtro durante la función wp_die (). Por lo tanto, cualquier complemento que funcione con ese filtro puede no funcionar si no incluimos wp_die (). También die () y otras funciones eliminan inmediatamente la ejecución de PHP sin considerar ninguna función de wordpress que debe considerarse al finalizar la ejecución.

Si está utilizando wp_send_json () dentro de usted, funciona de esta manera

       function my_action_callback()
    {
    // your code goes here

      wp_send_json();

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

    }

No es necesario usar wp_die () al final si incluye wp_send_json () dentro de la función de devolución de llamada . porque wordpress usa la función wp_die () de forma segura dentro de la función wp_send_json ().

Saran
fuente
2

Esto es solo además de lo que otros dijeron. La razón para preferir wp_diees que el núcleo puede desencadenar acciones allí y los complementos pueden completar correctamente cosas como el seguimiento, la supervisión o el almacenamiento en caché.

En general, siempre debe preferir una llamada a la API principal si está disponible, ya que probablemente agrega algún valor (almacenamiento en caché, integración de complementos o lo que sea) que no obtiene de la llamada directa de PHP.

Mark Kaplun
fuente
2

No aceptaré esta respuesta, esto no sería justo. Solo quería crear un esquema y posibles sugerencias sobre los elementos que considero importantes:

La definición principal 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: }

Por lo general, lo que obtenemos de la llamada ajax es algún tipo de respuesta. La respuesta puede estar codificada en json o no puede estar codificada en json.

En caso de que necesitemos json salida wp_send_jsono dos satélites son una gran idea.

Sin embargo, podemos regresar x-www-form-urlencodedo multipart/form-dataotext/xml o cualquier otro tipo de codificación. En ese caso no usamos wp_send_json.

Podemos devolver todo el html y en ese caso tiene sentido usar el wp_die()primer y el segundo parámetro, de lo contrario, estos parámetros deberían estar vacíos.

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

Pero, ¿cuál es un beneficio de llamar? wp_die() sin parámetros?


Finalmente, si revisas el gran núcleo de WP puedes 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();

Se utilizan ambos formatos. die() y wp_die(). ¿Puedes explicar porque?

Finalmente esto es lo que admin-ajax.php vuelvedie( '0' );

¿Por qué no wp_die(...)?

prosti
fuente
1

Uso wp_die(). Es mejor usar las funciones de WordPress tanto como puedas.

Greeso
fuente
1

Si lo usa echo, lo obligará a usar die()o die(0)o wp_die().

Si no lo usa echo, JavaScript puede manejar eso.

A continuación, se debe utilizar una mejor manera de devolver datos: wp_send_json().

Para enviar datos en su devolución de llamada (en jsonformato), puede usar lo siguiente:

wp_send_json()

wp_send_json_success()

wp_send_json_error()

Todos morirán por ti. No es necesario salir o morir después.

ACTUALIZAR

Y si no necesita jsoncomo formato de salida, debe usar:

wp_die($response)

Le devolverá su respuesta antes de que muera. Según el códice:

La función wp_die()está diseñada para dar salida justo antes de morir para evitar respuestas vacías o de tiempo de espera.

Lea el artículo completo del Codex aquí .

Faisal Alvi
fuente
1
Gracias, ¿qué sugieres en lugar de echo?
prosti
1
Para tener en cuenta, Javascript no maneja echo. wp_send_json_*usos echoy salidas para ti. Aquí hay confusión entre el cliente y el servidor.
Brian Fegter
@prosti wp_send_json ()
Faisal Alvi
Gracias, y en caso de que no necesitemos jsoncomo formato de salida?
prosti
1
@prosti de lo que debería usar wp_die ($ respuesta) porque según el códice: La función wp_die () está diseñada para dar salida justo antes de que muera para evitar respuestas vacías o de tiempo de espera.
Faisal Alvi