Programar tareas en Laravel sin editar crontab

Este capítulo empieza con una mentira; una mentira bien gorda. Laravel nos permite centralizar el trabajo de planificar las tareas pero sí hay que modificar el crontab. Eso sí, basta con una única línea en el crontab y nos podemos olvidar de él.

Gestionar tareas desde un cron en un pequeño sufrimiento. Además, si tenemos que hacer un cambio de servidor no tenemos que olvidar que hay un crontab de por medio que tenemos que copiar.

Por suerte, Laravel nos da las herramientas necesarias para hacer este trabajo más fácil.

Modificar el crontab

De este paso no nos libramos. Lo primero que debemos hacer es poner en marcha el planificador de tareas de Laravel.

Desde un terminal editamos nuestro cron:

$ crontab -e

Que nos abrirá un editor y deberemos añadir la siguiente línea:

* * * * * php /ruta/de/artisan schedule:run >> /dev/null 2>&1

Donde pone:

/ruta/de/artisan

debemos poner la ruta para acceder a Artisan, por ejemplo:

/var/www/vhosts/mi_proyecto_laravel/artisan

o puede que funcione simplemente con:

artisan

Esto tendrás que probarlo y dependerá de la configuración de tu servidor. Si tienes alguna dificultad con el cron echa un vistazo al capítulo Comprobar la ejecución de un cron y ver sus posibles errores.

Este cambio en el crontab es el que hace la magia. Cada minuto llama al comando Artisan schedule:run que es el que se encarga de mirar qué comandos hay que ejecutar.

Crear una nueva tarea

Las tareas se definen en el fichero app/Console/Kernel.php. Dentro de este archivo hay un método llamado schedule que es el que se encarga de lanzar las tareas.

Por ejemplo, en Gulvi hay una tarea que comprueba, cada hora, si hay algún artículo pendiente de publicar. Si se encuentra con algún artículo no publicado y cuya hora de publicación ya ha pasado cambia su estado para hacerlo visible.

Este código podría ser algo así:

    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            $chapters = Chapter::where('published', '=', false)->where('published_at', '<=', Carbon::now()->toDateTimeString())->get();
            foreach($chapters as $chapter) {
               // Código para hacer público el artículo, enviar a Twitter, etc.
            }
        })->hourly();
    }

NOTA: Dado que este artículo está pensado para principiantes he puesto el foreach, pero se puede usar la potencia de las colecciones. Hablaré de eso es otros vídeos.

La función call de $schedule ejecutará la esa función cada hora (gracias al ->hourly()) del final.

Esta función puede tener tantas tareas como queramos y cada una puede ejecutarse en un tiempo diferente. Unas tareas se puede ejecutar cada hora, otras cada minuto, otras mensualmente, etc.

Usar comandos Artisan

En cuanto empecemos a tener unas pocas tareas esta función va a crecer y convertirse en un monstruo. Para evitarlo podemos usar un comando Artisan.

NOTA: Echa un vistazo al artículo Crear un comando para Artisan.

Por ejemplo, para la tarea anterior podemos crear un comando llamado “capitulo:publicar” y lo podemos ejecutar cada hora de la siguiente forma:

$schedule->command('capitulo:publicar')->hourly();

Y dentro de este comando meteríamos el código anterior dentro de la función handle():

    public function handle()
    {
        $chapters = Chapter::where('published', '=', false)->where('published_at', '<=', Carbon::now()->toDateTimeString())->get();
        foreach($chapters as $chapter) {
            // Código para hacer público el artículo, enviar a Twitter, etc.
        }
    }

Usar comandos del sistema operativo

También podemos usar comandos del sistema con el método exec():

$schedule->exec('comando_del_sistema')->daily();

En el siguiente capitulo vamos a ver las distintas opciones que hay para los intervalos de tiempo y cómo evitar que se solapen las tareas.

Autor:
Nivel: Intermedio
Palabras clave:
Fecha publicado:
Fecha actualizado: 05-09-2016

Otros capítulos de la misma serie

Este capítulo es parte de la serie: Laravel pearls.

Y muchos más en preparación.

Disponible en los planes: Laravel hero