Error 400 bad request en admin-ajax.php usando solo el hook de acción wp_enqueue_scripts
He estado trabajando con ajax últimamente. Los tutoriales que encuentras en internet son todos muy similares y bastante fáciles de implementar.
Pero siempre obtengo un bad request 400 en mi archivo ajax-admin.php
.
Después de una larga e intensiva búsqueda, he descubierto que es debido al momento de la integración.
Si uso el hook de acción init
para inicializar el script y wp_localize_script
, todo funciona bien. Por lo que el código en sí debe ser correcto.
my-page-test-functions.php
function ajax_login_init(){
wp_register_script('ajax-login-script',get_stylesheet_directory_uri().'/js/ajax-login-script.js',array('jquery'));
wp_enqueue_script('ajax-login-script');
wp_localize_script('ajax-login-script','ajax_login_object',array('ajaxurl' => admin_url('admin-ajax.php'),'redirecturl' => 'URL_DE_REDIRECCION_AQUI','loadingmessage' => __('Enviando información del usuario, por favor espere...')));
add_action('wp_ajax_nopriv_ajaxlogin','ajax_login');
}
if(!is_user_logged_in()){
add_action('init','ajax_login_init');
}
function ajax_login(){
// el campo nonce se crea en la página
check_ajax_referer('ajax-login-nonce','security');
//CÓDIGO
die();
}
Pero si uso por ejemplo el hook de acción wp_enqeue_scripts
siempre obtengo el bad request.
if(!is_user_logged_in()){
add_action('wp_enqueue_scripts','ajax_login_init');
}
El problema con esto es:
Me gustaría tener las funciones en un archivo php extra y cargarlas solo si son necesarias en una página en particular. Para esto necesito, por ejemplo is_page()
.
Pero is_page()
funciona como muy pronto cuando engancho la función con el include en el hook de acción parse_query
:
functions.php
function sw18_page_specific_functions(){
if(is_page('page-test')){
include_once dirname(__FILE__).'/includes/my-page-test-functions.php';
}
}
add_action('parse_query','sw18_page_specific_functions');
Entonces las funciones enganchadas al hook init
en el archivo my-page-test-functions.php
no se disparan, supongo, porque init
viene antes que parse_query
.
¿Existe alguna mejor práctica para organizar esto, de manera que funcione? ¿O cómo puedo arreglar el bad request de admin-ajax.php
cuando uso el hook de acción wp_enqeue_scripts
?
Creo que lo único que falta aquí es que necesitas mover add_action('wp_ajax_nopriv_ajaxlogin','ajax_login');
fuera de ajax_login_init
.
Ese código registra tu manejador de Ajax, pero cuando solo lo ejecutas en wp_enqueue_scripts
, ya es demasiado tarde y los hooks de wp_ajax_nopriv_
ya se han ejecutado.
Entonces, ¿has probado algo como esto?
function ajax_login_init(){
if ( ! is_user_logged_in() || ! is_page( 'page-test' ) ) {
return;
}
wp_register_script('ajax-login-script',get_stylesheet_directory_uri().'/js/ajax-login-script.js',array('jquery'));
wp_enqueue_script('ajax-login-script');
wp_localize_script('ajax-login-script','ajax_login_object',array('ajaxurl' => admin_url('admin-ajax.php'),'redirecturl' => 'URL_DE_REDIRECCIÓN_AQUÍ','loadingmessage' => __('Enviando información del usuario, por favor espere...')));
}
add_action( 'wp_enqueue_scripts','ajax_login_init' );
add_action( 'wp_ajax_nopriv_ajaxlogin','ajax_login' );
function ajax_login(){
//nonce-field se crea en la página
check_ajax_referer('ajax-login-nonce','security');
//CÓDIGO
die();
}
Edición:
Ahora está más claro que solo quieres cargar el JavaScript en esa página en particular. Esto significa que necesitas poner tu is_page()
dentro de ajax_login_init()
. He actualizado el código en consecuencia.
Ahora, ¿por qué no funcionó tu solución?
La verificación is_page()
significaba que tu archivo de funciones solo se cargaba en esa página específica. ajax_login_init()
se llama y tus scripts se encolan. Hasta aquí todo bien.
Ahora tu script hace la llamada ajax. Como se mencionó en los comentarios, las llamadas ajax no son conscientes de la página actual en la que te encuentras. Hay una razón por la que el archivo está en wp-admin/admin-ajax.php
. No hay WP_Query
y por lo tanto is_page()
no funciona durante una solicitud ajax.
Como eso no funciona, sw18_page_specific_functions()
no hará nada en un contexto ajax. Esto significa que tu archivo de funciones no se carga y tu manejador ajax no existe.
Por eso necesitas incluir siempre ese archivo de funciones y mover esa verificación is_page()
dentro de ajax_login_init()
.
Así que en lugar de sw18_page_specific_functions() { … }
simplemente ejecuta include_once dirname(__FILE__).'/includes/my-page-test-functions.php';
directamente. Sin ninguna llamada a add_action( 'parse_query' )
.

Buena sugerencia. He cambiado eso (aún el mismo error), pero el problema sigue siendo que el archivo que contiene las funciones se cargará demasiado tarde. Pero necesito una forma de distinguir qué página se está utilizando. - actualmente intento esto con is_page() como se describió anteriormente.

¿Estás intentando ejecutar is_page()
desde dentro de ajax_login()
o desde dentro de ajax_login_init()
? El primero no puede funcionar porque está en un contexto Ajax.

He enumerado los archivos en los que están las funciones, como texto descriptivo arriba. El is_page() se usa en el functions.php y sirve para incluir el archivo con las funciones ajax solo cuando es necesario.

Recuerda que el nombre de la función 'action' debe estar añadido a la etiqueta wp_ajax_
.
function fetchorderrows() { // Esta función se ejecutará al enviar el ajax
// Haz cosas increíbles aquí todo el día
}
add_action('wp_ajax_fetchorderrows', 'fetchorderrows', 0);

En caso de que alguien esté utilizando un enfoque basado en clases y tenga problemas con el error 400 en AJAX, puede que necesite mover los manejadores de AJAX fuera de la clase (inténtalo en el archivo principal del plugin) y usar la clase y el método como segundo argumento.
add_action( 'wp_ajax_your_handle', [ 'Class_Name', 'function_name' ] );
add_action( 'wp_ajax_nopriv_your_handle', [ 'Class_Name', 'function_name' ] );

Hola Zee Xhan. Bienvenido/a al sitio. Tu respuesta necesita algunas revisiones. Primero, si tu respuesta es código, no publiques una captura de pantalla. En su lugar, publica el código como un fragmento y formatealo como código (usa el botón {}). Esa es probablemente la razón por la que tu respuesta fue votada negativamente y no fue aceptada. También, un poco más de explicación sería útil - como "por qué" simplemente escribir die(), y ¿dónde exactamente va esto en relación con el código en el OP (publicación original)?
