Como invalidar cache al guardar un post con hooks en PHP en WordPress

Contents

Introducción

Cuando trabajas con WordPress en sitios de producción es habitual utilizar varias capas de cache: caché de página (plugins como WP Rocket, W3 Total Cache, WP Super Cache), reverse proxies (Varnish, Nginx fastcgi_cache), CDN (Cloudflare, Fastly), y caché de objetos (Redis, Memcached). Si no invalidas adecuadamente esas cachés al guardar o actualizar un post, los usuarios pueden ver contenido desactualizado.

Objetivo de este tutorial

Explicar, paso a paso, cómo invalidar la caché cuando se guarda un post usando hooks de WordPress en PHP. Incluye comprobaciones de seguridad, estrategias según el tipo de caché y ejemplos de código listos para usar (cada ejemplo usa la etiqueta de código solicitada).

Resumen de la estrategia

  • Engancharse a los hooks apropiados: save_post, transition_post_status, wp_trash_post, etc.
  • Evitar ejecuciones innecesarias: autosaves, revisiones, permisos.
  • Limpiar la cache interna de WordPress (clean_post_cache).
  • Invocar métodos de purge específicos del plugin o proveedor (si existen).
  • Enviar purges al proxy/CDN (PURGE/BAN o API HTTP).
  • Hacer las purgas de forma no bloqueante o en background cuando la operación es lenta.

Hooks recomendados y buenas prácticas

  1. save_post — se ejecuta siempre que se guarda un post (creación/actualización). Recibe el ID del post, el objeto post y un flag update.
  2. transition_post_status — útil para detectar cambios de estado (draft → publish) y purgar solo en publicaciones públicas.
  3. wp_trash_post / before_delete_post — para limpiar caché al mover a la papelera o borrar.

Comprobaciones imprescindibles dentro del callback:

  • Evitar autosaves: defined(DOING_AUTOSAVE) DOING_AUTOSAVE
  • Evitar revisiones/autoguardados: wp_is_post_revision() y wp_is_post_autosave()
  • Control de permisos: current_user_can(edit_post, post_id)
  • Filtrar por post_type si solo interesa un tipo concreto (post, page, custom_post_type)

Ejemplo base: limpiar cache core y transients relacionados

Este ejemplo muestra cómo enganchar save_post y realizar las comprobaciones básicas, limpiar la cache de post del core y eliminar transients relacionados con el post si siguen una convención conocida.

post_type ) {
        // cambiar según necesidad
        return
    }

    // 1) Limpiar cache de objetos/metadata del core
    clean_post_cache( post_id )

    // 2) Eliminar transients que sigan una convención conocida (ejemplo)
    global wpdb
    like = % . wpdb->esc_like( mi_transient_post_ . post_id ) . %
    sql = wpdb->prepare( SELECT option_name FROM {wpdb->options} WHERE option_name LIKE %s, like )
    rows = wpdb->get_col( sql )
    if ( ! empty( rows ) ) {
        foreach ( rows as option_name ) {
            transient_key = preg_replace(/^_transient_/, , option_name)
            delete_transient( transient_key )
        }
    }

    // Opcional: disparar un action para otros listeners
    do_action( mi_cache_invalidate_after_save, post_id )
}
?>

Integraciones con plugins de caché populares

Es buena práctica comprobar si una función pública del plugin existe y llamarla solamente si está disponible, para evitar errores si el plugin no está instalado.

WP Rocket

WP Rocket expone funciones para purgar. Llamar a rocket_clean_post() si existe.


W3 Total Cache

W3TC dispone de funciones públicas para flush comprobar su existencia antes de llamar.


WP Super Cache

WP Super Cache puede requerir funciones específicas o limpieza de ficheros de cache en wp-content/cache/supercache/. Comprueba la API del plugin y actúa solo si las funciones están disponibles. Si no, puedes eliminar la carpeta supercache correspondiente al host/path.

Purge a reverse proxy (Varnish) mediante HTTP PURGE

Si usas Varnish o similar que acepte métodos PURGE, puedes hacer una petición HTTP con método PURGE a la URL del post. En muchos entornos Varnish solo acepta PURGE desde IPs permitidas, así que asegúrate de que tu servidor está autorizado.

 PURGE,
        timeout   => 2,
        blocking  => false,
        redirection => 5,
    ) )
}
add_action( save_post, mi_purge_varnish_por_url, 20, 1 )
?>

Purge en CDN (ejemplo: Cloudflare) mediante API

Cloudflare expone un endpoint REST para purgar por URL o por tag. Aquí un ejemplo que purga la URL del post usando el token de API de Cloudflare. Guarda el token y el zone_id en opciones o constantes seguras.

 array( url ) ) )

    args = array(
        headers => array(
            Authorization => Bearer  . token,
            Content-Type  => application/json,
        ),
        body      => body,
        timeout   => 5,
        blocking  => false, // evita bloquear la petición de guardado
    )

    wp_remote_post( endpoint, args )
}
add_action( save_post, mi_purge_cloudflare_post, 25, 1 )
?>

Estrategia para purgas no bloqueantes y en background

Si la invalidación es costosa (varias peticiones externas) es preferible delegarla a un proceso asíncrono:

  • wp_schedule_single_event() para ejecutar una tarea en background poco después.
  • wp_remote_post() con blocking => false para fire-and-forget.
  • Crear un endpoint REST protegido y llamarlo de manera no bloqueante desde el save_post.

Ejemplo simple con wp_schedule_single_event


Consideraciones avanzadas

  • Cache por etiquetas (tagging): algunos sistemas permiten purgar por tags en lugar de URLs si tu CDN/edge/Reverse Proxy soporta tags, úsalo para purgas más cortas y eficaces.
  • Purga selectiva: evita limpiar todo el cache si solo cambia un pequeño fragmento. Purga la URL del post y listas relacionadas (página principal, feed, categoría) en lugar del dominio entero.
  • Consistencia eventual: entiende que en arquitecturas distribuidas la invalidación puede tardar segundos o minutos en propagarse.
  • Logs y métricas: registra purgas fallidas para poder rehacerlas o alertar si hay problemas con el proveedor de CDN.

Checklist antes de desplegar

  1. Comprobar en staging que las funciones de purga no producen errores fatales si falta un plugin.
  2. Verificar permisos de IP para purges a Varnish o firewall para aceptar PURGE/BAN.
  3. Almacenar tokens/zone_id en opciones o constantes seguras (no hardcodearlos).
  4. Probar la purga en diferentes escenarios: crear, actualizar, cambiar estado (draft→publish), borrar.
  5. Evitar purgar en cada autosave purgar solo cuando el usuario realiza un guardado real o cambia el estado a publish.

Conclusión práctica

Invalidar la caché al guardar un post requiere combinar las comprobaciones adecuadas en los hooks y usar las APIs específicas de cada capa de caché (o el endpoint del CDN). Implementa primero la limpieza core (clean_post_cache), después funciones específicas de los plugins si existen y, finalmente, envía purges al proxy/CDN. Realiza las operaciones más costosas de manera asíncrona para no afectar la experiencia de edición.

Enlaces de interés (documentación oficial)

Puedes consultar la documentación oficial de los plugins y proveedores que uses para conocer las funciones públicas y los endpoints de purge. Si quieres introducir enlaces en el artículo, usa la etiqueta a con comillas simples, por ejemplo: clean_post_cache.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *