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 🙂 |