Contents
Introducción
Este tutorial explica paso a paso cómo cargar comentarios en WordPress de forma asíncrona usando la API REST y JavaScript (AJAX). La solución que proponemos crea un endpoint REST personalizado para insertar comentarios (compatible con comentarios para usuarios no autenticados y autenticados), gestiona la seguridad básica, prepara el script cliente y muestra cómo insertar el comentario en el DOM sin recargar la página.
Requisitos
- WordPress 4.7 (API REST incorporada).
- Acceso para editar functions.php o crear un plugin simple.
- Conocimientos básicos de PHP y JavaScript.
Flujo de trabajo
- Registrar un endpoint REST personalizado que valide y cree comentarios mediante wp_new_comment.
- Encolar y localizar un script JavaScript que capture el envío del formulario y realice un fetch POST al endpoint.
- Renderizar el comentario nuevo en el HTML de la página sin recarga, gestionando estados y errores.
1) Endpoint REST en PHP (functions.php o plugin)
Añade este código a functions.php de tu tema hijo o dentro de un plugin. El endpoint estará en /wp-json/my/v1/comment y aceptará POST con los campos mínimos: post, author, author_email, content. El código sanitiza entradas, verifica que los comentarios están abiertos y usa wp_new_comment para insertar el comentario.
POST,
callback => my_handle_comment,
permission_callback => __return_true // permitimos validación dentro del callback
))
})
function my_handle_comment( WP_REST_Request request ) {
params = request->get_json_params()
post_id = isset(params[post]) ? intval(params[post]) : 0
if ( ! post_id ! comments_open( post_id ) ) {
return new WP_REST_Response( array(
code => comments_closed,
message => Comentarios cerrados para este post.
), 400 )
}
author = isset(params[author]) ? sanitize_text_field( params[author] ) :
author_email = isset(params[author_email]) ? sanitize_email( params[author_email] ) :
content = isset(params[content]) ? wp_kses_post( params[content] ) :
if ( empty( content ) ) {
return new WP_REST_Response( array(
code => empty_content,
message => El comentario está vacío.
), 400 )
}
// Si el usuario está logueado, podemos recuperar su ID
user_id = get_current_user_id()
commentdata = array(
comment_post_ID => post_id,
comment_author => author,
comment_author_email => author_email,
comment_content => content,
user_id => user_id
)
// Inserta el comentario usando la API de WP
comment_id = wp_new_comment( commentdata )
if ( is_wp_error( comment_id ) ) {
return new WP_REST_Response( array(
code => insert_failed,
message => comment_id->get_error_message()
), 500 )
}
comment = get_comment( comment_id )
// Preparar respuesta mínima para renderizar en el cliente
response = array(
id => comment->comment_ID,
author => get_comment_author( comment->comment_ID ),
author_url => get_comment_author_url( comment->comment_ID ),
date => get_comment_date( , comment->comment_ID ),
content => apply_filters( comment_text, get_comment_text( comment ), comment ),
approved => comment->comment_approved
)
return new WP_REST_Response( response, 201 )
}
?>
2) Encolar y localizar el script JS
Encola el script que hará el envío por AJAX y pasa datos necesarios (URL base de REST, nonce, ID del post actual). Usa wp_localize_script (o wp_add_inline_script) para exponer esos valores al script cliente.
esc_url_raw( rest_url() ),
nonce => wp_create_nonce( wp_rest ),
post_id => get_the_ID()
))
})
?>
3) Formulario HTML
Ejemplo mínimo de formulario de comentarios que puedes colocar en single.php o en la plantilla de comentarios. Este formulario será interceptado por JavaScript.
4) Script JavaScript (cliente)
Ejemplo de my-ajax-comments.js que recoge los datos, llama al endpoint y añade el comentario al DOM. Importante: usar credentials:same-origin para incluir cookies si fuera necesario y enviar X-WP-Nonce si el usuario está autenticado.
(function() {
// MY_COMMENTS_DATA viene de wp_localize_script
const restBase = (typeof MY_COMMENTS_DATA !== undefined MY_COMMENTS_DATA.rest_url) ? MY_COMMENTS_DATA.rest_url : /wp-json/
const endpoint = restBase my/v1/comment
const nonce = (typeof MY_COMMENTS_DATA !== undefined) ? MY_COMMENTS_DATA.nonce :
const postID = (typeof MY_COMMENTS_DATA !== undefined) ? MY_COMMENTS_DATA.post_id : null
const form = document.getElementById(ajax-comment-form)
const list = document.getElementById(comment-list)
const submitBtn = document.getElementById(comment-submit)
function escapeHtml(unsafe) {
return unsafe.replace(/[<>]/g, function(m) {
return ({:amp,<:lt,>:gt,:quot,:#039})[m]
})
}
function createCommentHTML(data) {
// data: {id, author, date, content, approved}
var li = document.createElement(li)
li.id = comment- data.id
var header = document.createElement(p)
header.innerHTML = escapeHtml(data.author) escapeHtml(data.date)
li.appendChild(header)
var content = document.createElement(div)
// Si el comentario no está aprobado, mostrar aviso
if (String(data.approved) !== 1) {
var pending = document.createElement(em)
pending.textContent = Tu comentario está pendiente de moderación.
li.appendChild(pending)
}
// Insertamos el HTML seguro retornado por el servidor (ya sanitizado por wp_kses_post)
content.innerHTML = data.content
li.appendChild(content)
return li
}
function setLoading(state) {
if (state) {
submitBtn.disabled = true
submitBtn.textContent = Enviando...
} else {
submitBtn.disabled = false
submitBtn.textContent = Enviar comentario
}
}
if (!form) return
form.addEventListener(submit, function(e) {
e.preventDefault()
var author = document.getElementById(author).value.trim()
var author_email = document.getElementById(email).value.trim()
var content = document.getElementById(comment).value.trim()
if (!content) {
alert(El comentario no puede estar vacío.)
return
}
setLoading(true)
var payload = {
post: postID,
author: author,
author_email: author_email,
content: content
}
fetch(endpoint, {
method: POST,
credentials: same-origin,
headers: {
Content-Type: application/json,
X-WP-Nonce: nonce
},
body: JSON.stringify(payload)
})
.then(function(response) {
setLoading(false)
if (!response.ok) return response.json().then(function(err) { throw err })
return response.json()
})
.then(function(data) {
// Insertar el comentario en la lista sin recargar
var li = createCommentHTML(data)
if (list) list.insertBefore(li, list.firstChild)
// Limpiar formulario
form.reset()
})
.catch(function(err) {
console.error(Error al enviar el comentario:, err)
var msg = (err err.message) ? err.message : Error desconocido
alert(No se pudo enviar el comentario: msg)
})
})
})()
5) Seguridad y validaciones adicionales
- Sanitización: En el backend usamos sanitize_text_field, sanitize_email y wp_kses_post para el contenido. Ajusta las etiquetas permitidas si lo necesitas.
- Nonce: Enviamos X-WP-Nonce para usuarios autenticados para usuarios no autenticados el endpoint permite insertar comentarios si comments_open es true. Si se necesita más seguridad (antispam), añade verificación adicional.
- Spam: Integrar Akismet, reCAPTCHA o medidas personalizadas. Se puede validar reCAPTCHA en el servidor antes de insertar el comentario.
- Moderación: wp_new_comment aplica las reglas de moderación configuradas en WordPress. El campo comment_approved depende de la configuración de la instalación.
6) Consideraciones de accesibilidad y UX
- Deshabilita el botón mientras se envía para evitar envíos duplicados.
- Proporciona mensajes claros (pendiente de moderación, error, éxito).
- Añade etiquetas aria-live si quieres que los lectores de pantalla informen de nuevos mensajes o errores.
7) Casos especiales y extensiones
- Usuarios logueados: Puedes auto-rellenar nombre/email desde current_user y omitir esos campos en el formulario.
- Responder a un comentario: Añade un campo parent al payload y pásalo a wp_new_comment para establecer la jerarquía.
- Renderizado avanzado: Si necesitas el mismo HTML que renderiza tu tema, puedes devolver desde el endpoint un fragmento HTML generado con get_comment_text y plantillas, o usar renderers personalizados en PHP.
8) Depuración
- Revisa la consola del navegador para errores CORS o de fetch.
- Habilita WP_DEBUG para capturar errores PHP del endpoint.
- Verifica las respuestas JSON del endpoint (códigos HTTP y mensajes).
Conclusión
Con este enfoque tienes un flujo completo para enviar comentarios por AJAX usando la REST API de WordPress: un endpoint controlado por PHP, un script cliente que realiza la petición y actualiza la UI y consideraciones de seguridad y acceso. A partir de aquí puedes integrar antispam, mejorar el renderizado del comentario y adaptar la UX a tus necesidades.
|
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |
