Como programar tareas con wp_cron y eventos recurrentes en PHP en WordPress

Introducción: wp_cron es el sistema interno de WordPress para programar tareas (cron jobs) mediante eventos. No es un cron del sistema: se dispara cuando hay visitas al sitio o cuando se invoca manualmente. En este artículo encontrarás explicaciones técnicas, ejemplos completos en PHP, buenas prácticas, cómo crear intervalos personalizados, cómo programar y desprogramar eventos, y alternativas cuando wp_cron no es suficiente.

Contents

Conceptos clave

  • Hook (evento): Una cadena que identifica la tarea programada (ej. mi_plugin_evento).
  • Recurrencia: Intervalo predefinido (hourly, twicedaily, daily) o personalizado mediante el filtro cron_schedules.
  • Timestamp: Marca temporal Unix en segundos que indica cuándo debe ejecutarse el próximo evento.
  • Activación/Desactivación: En plugins, es habitual programar en la activación y limpiar en la desactivación.
  • Limitaciones: WP-Cron depende del tráfico para ejecución fiable usar cron del sistema que llame a wp-cron.php o alternativas como Action Scheduler.

Diferencias con cron del sistema

  • cron del sistema: ejecuta tareas a nivel del servidor según programación exacta (muy fiable).
  • wp_cron: se ejecuta en peticiones HTTP (no en tiempo real en sitios sin tráfico) a menos que configures un cron real que llame a wp-cron.php.

Funciones principales que debes conocer

Función Uso
wp_schedule_event Programa un evento recurrente.
wp_schedule_single_event Programa un evento único (no recurrente).
wp_next_scheduled Obtiene el timestamp del próximo evento programado para un hook (y args opcionales).
wp_clear_scheduled_hook Elimina todas las programaciones asociadas a un hook (opcionalmente filtrando por args).
wp_unschedule_event Elimina una instancia concreta de un evento indicando timestamp, hook y args.

Buenas prácticas

  • Comprobar con wp_next_scheduled antes de programar para evitar duplicados.
  • Usar current_time(timestamp) si quieres respetar la zona horaria de WordPress en muchos casos time() también funciona, pero current_time es más coherente con WP.
  • Hacer tareas idempotentes: si una tarea se ejecuta dos veces por error, no debe provocar resultados inconsistentes.
  • No ejecutar procesos largos dentro de la rutina usar colas o bibliotecas de background processing (Action Scheduler, WP Background Processing).
  • En producción, desactivar el WP-Cron embebido y usar un cron del sistema que llame periódicamente a wp-cron.php para mayor fiabilidad.

Ejemplo completo: plugin mínimo que programa un evento recurrente (cada 10 minutos), lo ejecuta y lo limpia

Este ejemplo muestra: añadir un intervalo personalizado, programar en la activación, manejar el hook, y limpiar en la desactivación. Comprueba siempre wp_next_scheduled antes de programar para evitar duplicados.

lt?php
/
  Plugin Name: Mi Scheduler Ejemplo
  Description: Ejemplo de wp_cron con intervalo personalizado y manejo de activación/desactivación.
  Version: 1.0
  Author: Tu Nombre
 /

// 1) Añadir intervalo personalizado (cada 10 minutos)
add_filter(cron_schedules, mi_plugin_cron_schedules)
function mi_plugin_cron_schedules(schedules) {
    if (! isset(schedules[every_ten_minutes])) {
        schedules[every_ten_minutes] = array(
            interval => 10  60, // 10 minutos en segundos
            display  => Cada 10 minutos
        )
    }
    return schedules
}

// 2) Acción que ejecuta la tarea
add_action(mi_plugin_evento_recurrente, mi_plugin_ejecutar_tarea)
function mi_plugin_ejecutar_tarea(args = array()) {
    // Ejemplo: limpiar transients viejos, enviar un request, generar un informe, etc.
    // Hacer la lógica aquí. Debe ser eficiente y segura.
    // Se puede usar args pasado desde la programación si es necesario.
    error_log(mi_plugin_ejecutar_tarea ejecutado a  . date(c))
    // ... resto de la lógica ...
}

// 3) Programar en la activación del plugin
register_activation_hook(__FILE__, mi_plugin_activar)
function mi_plugin_activar() {
    // Evitar duplicados
    if (! wp_next_scheduled(mi_plugin_evento_recurrente)) {
        // Usamos current_time(timestamp) para respetar la zona horaria de WP
        timestamp = current_time(timestamp)
        wp_schedule_event(timestamp, every_ten_minutes, mi_plugin_evento_recurrente)
    }
}

// 4) Limpiar en la desactivación del plugin
register_deactivation_hook(__FILE__, mi_plugin_desactivar)
function mi_plugin_desactivar() {
    // Eliminar todas las instancias programadas para este hook
    wp_clear_scheduled_hook(mi_plugin_evento_recurrente)
}
?gt

Notas sobre el ejemplo

  • Si necesitas pasar argumentos al callback, wp_schedule_event acepta un cuarto parámetro args (array). Para comprobar una tarea específica usa wp_next_scheduled(hook, args).
  • Si prefieres programar un evento único: wp_schedule_single_event(timestamp, mi_hook, args).

Programar eventos únicos y cómo cancelarlos

Ejemplo de evento único y su cancelación:

// Programar evento único para dentro de 5 minutos
when = time()   5  60
args = array(id => 123)
wp_schedule_single_event(when, mi_evento_unico, args)

// Para ver cuándo se ejecutará:
next = wp_next_scheduled(mi_evento_unico, args)

// Para cancelar esa instancia concreta:
if (next) {
    wp_unschedule_event(next, mi_evento_unico, args)
}

// Para eliminar todas las instancias de mi_evento_unico (sin importar args):
wp_clear_scheduled_hook(mi_evento_unico)

Usar argumentos (args) para diferenciar tareas

Pasar args es útil cuando quieres múltiples programaciones del mismo hook con parámetros distintos (por ejemplo, procesar distintos IDs). Al programar y desprogramar, incluye los mismos args para manipular esa instancia concreta.

Depuración y pruebas

  • Usa error_log o registros personalizados para verificar ejecuciones durante desarrollo.
  • WP-CLI: puedes listar y ejecutar eventos:
# Listar eventos programados
wp cron event list

# Ejecutar el siguiente evento en cola
wp cron event run --due-now

# Ejecutar un evento por nombre (ej. mi_plugin_evento_recurrente)
wp cron event run mi_plugin_evento_recurrente

Hacer fiable wp_cron en producción

  1. En wp-config.php añadir:
    define(DISABLE_WP_CRON, true)
        
  2. Crear una tarea del sistema (crontab) que invoque wp-cron.php cada N minutos. Ejemplo (Linux):
# Editar crontab con crontab -e
# Ejecutar wp-cron.php cada 5 minutos usando wget
/5     wget -q -O - https://tusitio.com/wp-cron.php?doing_wp_cron >/dev/null 2>1

# O usando curl
/5     curl -s https://tusitio.com/wp-cron.php?doing_wp_cron >/dev/null 2>1

Ventajas

  • Consistencia en ejecución independiente del tráfico.
  • Control absoluto sobre la frecuencia.

Limitaciones comunes y soluciones

  • Problema: tareas que se solapan o que tardan demasiado. Solución: implementar locking (transients o opciones) para evitar reentradas, o delegar a una cola asíncrona.
  • Problema: tareas no se ejecutan en sitios sin tráfico. Solución: programar cron real (ver arriba) o usar un servicio externo.
  • Problema: exceso de load por ejecutar muchas tareas simultáneas. Solución: escalonar, usar argumentos para repartir carga, o usar Action Scheduler para manejo avanzado.

Alternativas avanzadas

  • Action Scheduler: biblioteca usada por WooCommerce para manejar colas de tareas, reintentos y procesamiento en background.
  • WP Background Processing: patrón para procesar lotes en background.
  • Trabajos en segundo plano con colas externas: usar Redis/Beanstalkd/RabbitMQ y workers para tareas críticas o muy intensivas.

Resumen práctico

  • Usa wp_schedule_event para recurrencias y wp_schedule_single_event para tareas únicas.
  • Evita duplicados con wp_next_scheduled.
  • Para fiabilidad en producción, deshabilita wp_cron embebido y usa cron del sistema para llamar a wp-cron.php.
  • Para tareas complejas o críticas, considera Action Scheduler o un sistema de colas.

Recursos útiles (comandos y funciones)

  • Funciones: wp_schedule_event, wp_schedule_single_event, wp_next_scheduled, wp_unschedule_event, wp_clear_scheduled_hook, add_filter(cron_schedules, …).
  • WP-CLI: wp cron event list, wp cron event run.

Con lo anterior tienes todo lo necesario para programar tareas con wp_cron y eventos recurrentes en PHP, desde ejemplos prácticos hasta recomendaciones para entornos productivos y alternativas más robustas cuando la necesidad lo requiera.



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 *