En este tutorial detallado aprenderás a interceptar el guardado de entradas (posts) en WordPress para generar slugs personalizados en PHP. Se muestran las mejores prácticas, dos enfoques comunes (filtrar antes de insertar y ajustar después de guardar), cómo evitar bucles infinitos, cómo garantizar unicidad, transliteración y ejemplos prácticos listos para usar en temas o plugins.
Contents
Por qué interceptar el guardado del post
- Automatizar slugs basados en campos personalizados: por ejemplo generar el slug con un ACF o metadato concreto.
- Aplicar reglas de negocio: normalizar slugs con prefijos, sufijos, añadir fecha o estructura personalizada.
- Control multilenguaje o transliteración: generar slugs consistentes para idiomas con caracteres especiales.
- Estandarizar SEO: aplicar un formato definido para todos los contenidos.
Hooks útiles y cuándo usarlos
Hook | Cuándo | Ventajas | Inconvenientes |
---|---|---|---|
wp_insert_post_data | Antes de que WordPress inserte/actualice el post en la base de datos (filtrando los datos). | Evita llamadas extra a la DB ideal para modificar post_name antes del guardado. | Se ejecuta tanto en inserciones como en actualizaciones hay que contemplar revisiones/autosaves. |
save_post | Después de que el post ha sido guardado. | Acceso al ID del post y a metadatos recién guardados útil si el slug depende de campos que se guardan en el mismo proceso. | Si actualizas el post dentro de este hook, debes evitar recursividad (remove_action). |
Recomendaciones previas (chequeos comunes)
- Ignorar revisiones y autosaves: wp_is_post_revision(), wp_is_post_autosave(), DOING_AUTOSAVE.
- Comprobar el tipo de post: data[post_type] o post->post_type.
- Comprobar capacidades si procede: current_user_can(edit_post, post_ID).
- Evitar actuar en REST requests/AJAX si no corresponde: defined(REST_REQUEST) o defined(DOING_AJAX).
- Usar funciones de sanitización de WP: sanitize_title_with_dashes(), remove_accents(), wp_unique_post_slug().
Método recomendado A: Modificar el slug antes de guardar (wp_insert_post_data)
Este es el método más limpio porque modifica post_name antes de que WordPress haga la inserción/actualización, evitando una segunda actualización de post.
Explicación rápida
- Filtramos wp_insert_post_data para intervenir antes del guardado final.
- Hacemos checks de revisión/autosave y tipo de post.
- Generamos la base del slug (campo personalizado o título) y la sanitizamos.
- Usamos wp_unique_post_slug para evitar colisiones.
- Asignamos post_name y devolvemos los datos.
Método alternativo B: Ajustar el slug después del guardado (save_post)
Útil cuando el slug depende de metadatos que se guardan en el mismo proceso y no están disponibles en wp_insert_post_data (por ejemplo ACF que guarda en save_post).
post_type ) { return } // Comprobar permisos: el usuario actual puede editar el post if ( ! current_user_can( edit_post, post_ID ) ) { return } // Obtener valor a partir de un campo meta guardado (ejemplo con ACF) mi_campo = get_post_meta( post_ID, mi_campo_slug, true ) // Si no hay campo, fallback al título source = ! empty( mi_campo ) ? mi_campo : post->post_title // Generar slug y sanitizar slug_base = sanitize_title_with_dashes( source ) unique_slug = wp_unique_post_slug( slug_base, post_ID, post->post_status, post->post_type, post->post_parent ) // Si ya es igual, no hacer nada (evita actualización innecesaria) if ( unique_slug === post->post_name ) { return } // Evitar recursividad: remover el hook, actualizar, volver a añadir remove_action( save_post, mi_sluggenerador_save_post, 10 ) wp_update_post( array( ID => post_ID, post_name => unique_slug ) ) add_action( save_post, mi_sluggenerador_save_post, 10, 3 ) } ?>
Puntos clave de este enfoque
- Se comprueba que el nuevo slug realmente cambia antes de llamar a wp_update_post.
- Se elimina temporalmente la acción para evitar recursividad cuando se actualiza el post dentro del hook.
- Puede ser necesario si dependes de metadatos que solo existen tras el primer guardado.
Generador de slugs avanzado (transliteración y fallback)
En entornos multilengua o con caracteres no latinos, conviene transliterar (remove_accents o iconv) y aplicar reglas adicionales (prefijos, sufijos, fecha, ID si hace falta). Ejemplo completo de helper:
Casos especiales y consideraciones
- Bulk edits y quick-edit: ten en cuenta que el flujo de guardado difiere comprueba que tu lógica cubre estos casos.
- REST API: si quieres interceptar guardados realizados vía REST, comprueba la constante REST_REQUEST y si necesitas actuar en este flujo.
- Permalinks y flush: no es necesario hacer flush_rewrite_rules al cambiar slugs de posts individuales. Flush solo cuando cambian reglas de reescritura.
- Rendimiento: evita consultas innecesarias prefiere wp_insert_post_data para no ejecutar wp_update_post extra.
- Auditoría/Redirecciones: si cambias slugs en posts ya indexados, considera crear redirecciones 301 desde el slug antiguo al nuevo para no perder SEO.
Pruebas recomendadas antes de ponerlo en producción
- Probar con títulos con caracteres especiales (acentos, ñ, caracteres no latinos).
- Comprobar en creación, edición, quick-edit y bulk edit.
- Probar en REST API y en envíos desde frontend (si aplica).
- Probar con tipos de post personalizados y con jerarquías parent/child.
- Verificar que no hay bucles en logs ni cargas extra de DB.
Resumen final
La forma más limpia y eficiente generalmente es usar wp_insert_post_data para modificar post_name antes del guardado. Si dependes de metadatos que solo existen tras guardar, usa save_post con remove_action/añadir acción para evitar recursividad. Siempre sanitiza, translitera si procede y usa wp_unique_post_slug para evitar colisiones. Comprueba revisiones, autosaves y capacidades para no interferir con procesos internos de WordPress.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |