El método correcto para pasar variables de consulta en AJAX usando ajaxurl
OK, no tenía idea de cómo titular este tema.
Estoy intentando sobrescribir el comportamiento predeterminado con ajax. El problema aquí no es realmente un problema, sino más bien un deseo.
Tengo esta URL:
<a href="http://example.com/?reaction=smk_remove_post&id=1226&_nonce=7be82cd4a0" class="smk-remove-post">Eliminar post</a>
En el archivo functions.php
tengo esta función y su llamada justo después:
function smk_remove_post(){
if( !empty( $_GET['reaction'] ) && 'smk_remove_post' == $_GET['reaction'] && !empty( $_GET['id'] ) ){
if( current_user_can('edit_others_posts') && !empty($_GET['_nonce']) ){
if( wp_verify_nonce( esc_html( $_GET['_nonce'] ), 'smk_remove_post' ) ){
// Eliminar el post
wp_delete_post( absint( $_GET['id'] ), true );
}
}
}
}
smk_remove_post();
Ahora, si hago clic en el enlace, el post con ID 1226
será eliminado. Todo está bien. La tarea se completa exitosamente y la página se recarga.
Aquí es donde necesito AJAX. Quiero procesar esta URL usando ajax y no recargar la página, y obtener una respuesta adecuada.
He añadido este script jQuery:
function smk_remove_post(){
$('.smk-remove-post').on( 'click', function( event ){
event.preventDefault();
var _this = $(this);
jQuery.ajax({
type: "GET",
url: _this.attr('href'),
success: function(response){
console.log(response);
_this.text('Todo bien, el post ha sido eliminado.');
}
});
});
}
smk_remove_post();
Todo funciona como se espera. El post se elimina via ajax y no es necesario recargar la página. Pero no puedo obtener una respuesta adecuada, en su lugar obtengo todo el código HTML fuente de la página actual.
Sé que debería usar admin-ajax.php
(ajaxurl), pero ¿cómo lo hago? Necesito enviar la consulta desde la URL y obtener la respuesta de vuelta.
Esto es lo que he intentado:
He añadido esto al script jQuery anterior:
data: {
'action': 'smk_remove_post_ajax',
},
Y esto al PHP:
function smk_remove_post_ajax(){
smk_remove_post();
die();
}
add_action('wp_ajax_smk_remove_post_ajax', 'smk_remove_post_ajax');
No funciona. Se ignora, la llamada anterior se ejecuta en su lugar, como si esto se hubiera hecho sin ajax.
Entiendo que necesito enviar la consulta a admin-ajax.php de alguna manera, pero ¿cómo?
Finalmente lo conseguí.
El primer error fue procesar la misma función dos veces. La llamé una vez después de la función y una vez más en la acción ajax. Así que al usar la llamada ajax, la función se ejecutó dos veces. En el ejemplo del OP, esto no es un problema en absoluto, porque está simplificado para hacer solo una cosa, pero en mi código real hace mucho más y puede resultar en pérdida de datos no deseados.
Además, solo necesitaba detener el ajax y obtener una respuesta personalizada, nada más. Esto es lo que hice:
1. Cambié esto:
smk_remove_post();
por esto:
add_action('parse_query', 'smk_remove_post');
Es mejor ejecutar la función más tarde cuando sea necesario en una acción especial.
2. Luego, modifiqué el manejador ajax:
Eliminé esta línea smk_remove_post();
y cambié la acción ajax de wp_ajax_smk_remove_post_ajax
a wp_ajax_smk_remove_post
:
function smk_remove_post_ajax(){
wp_die( 'ok' );
}
add_action('wp_ajax_smk_remove_post', 'smk_remove_post_ajax');
3. Renombré el query string reaction
a action
. Lo cambié en la URL y en la función:
4. Finalmente modifiqué el script jQuery. Para que use admin-ajax.php y envíe la URL como datos:
url: ajaxurl,
data: _this.attr('href'),
Aquí está el código final:
Enlace:
<a href="http://example.com/?action=smk_remove_post&id=1226&_nonce=7be82cd4a0" class="smk-remove-post">Eliminar publicación</a>
Código PHP:
function smk_remove_post(){
if( !empty( $_GET['action'] ) && 'smk_remove_post' == $_GET['action'] && !empty( $_GET['id'] ) ){
if( current_user_can('edit_others_posts') && !empty($_GET['_nonce']) ){
if( wp_verify_nonce( esc_html( $_GET['_nonce'] ), 'smk_remove_post' ) ){
// Eliminar la publicación
wp_delete_post( absint( $_GET['id'] ), true );
}
}
}
}
add_action('parse_query', 'smk_remove_post');
function smk_remove_post_ajax(){
wp_die( 'ok' );
}
add_action('wp_ajax_smk_remove_post', 'smk_remove_post_ajax');
Javascript:
function smk_remove_post(){
$('.smk-remove-post').on( 'click', function( event ){
event.preventDefault();
var _this = $(this);
jQuery.ajax({
type: "GET",
url: ajaxurl,
data: _this.attr('href').split('?')[1],
success: function(response){
console.log(response); // ok
_this.text('Todo bien, la publicación ha sido eliminada.');
}
});
});
}
smk_remove_post();
Edición:
También una pequeña actualización al código anterior. Para procesar los query strings es necesario eliminar la ruta del sitio, de lo contrario puede crear problemas inesperados. Añadí esto a data href
:
.split('?')[1]

Crea un enlace como este
<a href="http://example.com/?reaction=smk_remove_post&id=1226&_nonce=7be82cd4a0" data-id="1226" data-nonce="7be82cd4a0" class="smk-remove-post">Eliminar publicación</a>
Y el código jQuery
$('.smk-remove-post').on( 'click', function( event ){
event.preventDefault();
var _this = $(this);
var data = {
'action': 'smk_remove_post_ajax',
'reaction': 'smk_remove_post',
'id': _this.data('id'),
'_nonce': _this.data('nonce')
};
// desde la versión 2.8 ajaxurl siempre está definido en la cabecera del admin y apunta a admin-ajax.php
jQuery.ajax({
type: "GET",
url: ajaxurl,
data: data,
success: function(response){
console.log(response);
_this.text('Todo correcto, la publicación ha sido eliminada.');
}
});
});
Consulta el Codex sobre AJAX en Plugins. Y en el Codex, dice:
La mayoría de las veces deberías usar wp_die() en tu función de callback Ajax. Esto proporciona una mejor integración con WordPress y facilita las pruebas de tu código.
Así que usa wp_die();
en lugar de die();

Esto es lo que he usado antes, pero aquí necesito que el código funcione con o sin ajax.

Si desactivo el javascript, volverá a recargar la página y procesará la acción sin ajax. En tu ejemplo solo funcionará si JS está habilitado.

AJAX no es mágico y cuando solicitas la URL X recibirás el mismo HTML para esa URL si lo haces desde la barra de direcciones del navegador, un enlace o AJAX. Por lo tanto, si deseas una respuesta diferente al HTML, no puedes usar la misma URL para la solicitud AJAX que en el enlace.
WordPress tiene un "end point" especial para manejar solicitudes AJAX: admin-ajax.php, y todas las solicitudes AJAX deben enviarse solo a él, algo como $.ajax({url:....admin-ajax.php})
.
Luego, debes hacerle saber a WordPress lo que deseas hacer, y para eso hay un parámetro especial en la solicitud llamado action
. Este parámetro identificará el hook que se usará en el lado del servidor para manejar la solicitud. Esta parte la has hecho correctamente en tu código.
Ahora necesitas los parámetros adicionales que identifican qué objeto debe ser manipulado o recuperado por la operación AJAX. Puedes usar el enlace permanente (permalink) de la publicación o el ID de la publicación, por ejemplo, pero todo depende de la complejidad de la operación que intentas realizar. En tu caso específico, supongo que un ID de publicación será el mejor parámetro para pasar en la solicitud.
¿Cómo enviar los parámetros? La mayoría de las personas hacen una solicitud POST cuando realizan AJAX, pero si deseas un GET, puedes pasarlos como parte de la URL (lo que supongo es exactamente lo que jQuery hará por ti).
