Laravel 5.4 Agendamento de tarefas

Introdução

No passado, você pode ter gerado uma entrada Cron para cada tarefa que precisava agendar em seu servidor. No entanto, isso pode se tornar um problema rapidamente, porque o agendamento da sua tarefa não está mais no controle de origem e você deve executar o SSH no servidor para adicionar mais entradas do Cron.

O programador de comandos do Laravel permite que você defina de forma fluente e expressiva seu cronograma de comando dentro do próprio Laravel. Ao usar o agendador, apenas uma única entrada Cron é necessária no seu servidor. Sua agenda de tarefas é definida no método app/Console/Kernel.phpdo arquivo schedule. Para ajudar você a começar, um exemplo simples é definido dentro do método.

Iniciando o Agendador

Ao usar o agendador, você só precisa adicionar a seguinte entrada Cron ao seu servidor. Se você não souber como adicionar entradas do Cron ao seu servidor, considere usar um serviço como o Laravel Forge, que pode gerenciar as entradas do Cron para você:

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

Este Cron irá chamar o programador de comandos do Laravel a cada minuto. Quando o schedule:runcomando é executado, o Laravel avaliará suas tarefas agendadas e executará as tarefas vencidas.

Definindo Horários

Você pode definir todas as suas tarefas agendadas no schedulemétodo da App\Console\Kernelclasse. Para começar, vamos ver um exemplo de agendamento de uma tarefa. Neste exemplo, vamos agendar um Closurepara ser chamado todos os dias à meia-noite. No interior Closure, vamos executar uma consulta ao banco de dados para limpar uma tabela:

<?php

namespace App\Console;

use DB;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        \App\Console\Commands\Inspire::class,
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            DB::table('recent_users')->delete();
        })->daily();
    }
}

Além de agendar Closurechamadas, você também pode agendar comandos do Artisan e comandosdo sistema operacional. Por exemplo, você pode usar o commandmétodo para agendar um comando Artisan usando o nome ou a classe do comando:

$schedule->command('emails:send --force')->daily();

$schedule->command(EmailsCommand::class, ['--force'])->daily();

execcomando pode ser usado para emitir um comando para o sistema operacional:

$schedule->exec('node /home/forge/script.js')->daily();

Agendar opções de frequência

Claro, há uma variedade de horários que você pode atribuir à sua tarefa:

Método Descrição
->cron('* * * * * *'); Executar a tarefa em um cronograma personalizado do Cron
->everyMinute(); Execute a tarefa a cada minuto
->everyFiveMinutes(); Execute a tarefa a cada cinco minutos
->everyTenMinutes(); Execute a tarefa a cada dez minutos
->everyThirtyMinutes(); Execute a tarefa a cada trinta minutos
->hourly(); Execute a tarefa a cada hora
->hourlyAt(17); Execute a tarefa a cada hora a 17 minutos após a hora
->daily(); Execute a tarefa todos os dias à meia-noite
->dailyAt('13:00'); Execute a tarefa todos os dias às 13:00
->twiceDaily(1, 13); Execute a tarefa diariamente às 1:00 e 13:00
->weekly(); Execute a tarefa toda semana
->monthly(); Execute a tarefa todos os meses
->monthlyOn(4, '15:00'); Execute a tarefa todos os meses no dia 4 às 15:00
->quarterly(); Execute a tarefa a cada trimestre
->yearly(); Execute a tarefa todos os anos
->timezone('America/New_York'); Definir o fuso horário

Esses métodos podem ser combinados com restrições adicionais para criar agendas ainda mais afinadas que são executadas somente em determinados dias da semana. Por exemplo, para agendar um comando para ser executado semanalmente na segunda-feira:

// Run once per week on Monday at 1 PM...
$schedule->call(function () {
    //
})->weekly()->mondays()->at('13:00');

// Run hourly from 8 AM to 5 PM on weekdays...
$schedule->command('foo')
          ->weekdays()
          ->hourly()
          ->timezone('America/Chicago')
          ->between('8:00', '17:00');

Abaixo está uma lista das restrições adicionais do cronograma:

Método Descrição
->weekdays(); Limitar a tarefa aos dias da semana
->sundays(); Limitar a tarefa ao domingo
->mondays(); Limitar a tarefa a segunda-feira
->tuesdays(); Limite a tarefa a terça-feira
->wednesdays(); Limite a tarefa a quarta-feira
->thursdays(); Limite a tarefa a quinta-feira
->fridays(); Limite a tarefa a sexta-feira
->saturdays(); Limitar a tarefa a sábado
->between($start, $end); Limitar a tarefa a ser executada entre os horários de início e término
->when(Closure); Limite a tarefa com base em um teste de verdade

Entre restrições de tempo

betweenmétodo pode ser usado para limitar a execução de uma tarefa com base na hora do dia:

$schedule->command('reminders:send')
                    ->hourly()
                    ->between('7:00', '22:00');

Da mesma forma, o unlessBetweenmétodo pode ser usado para excluir a execução de uma tarefa por um período de tempo:

$schedule->command('reminders:send')
                    ->hourly()
                    ->unlessBetween('23:00', '4:00');

Restrições do teste de verdade

whenmétodo pode ser usado para limitar a execução de uma tarefa com base no resultado de um determinado teste de verdade. Em outras palavras, se os Closureretornos fornecidos true, a tarefa será executada, desde que nenhuma outra condição de restrição impeça a execução da tarefa:

$schedule->command('emails:send')->daily()->when(function () {
    return true;
});

skipmétodo pode ser visto como o inverso de when. Se o skipmétodo retornar true, a tarefa agendada não será executada:

$schedule->command('emails:send')->daily()->skip(function () {
    return true;
});

Ao usar whenmétodos encadeados , o comando planejado só será executado se todas as whencondições retornarem true.

Prevenção de sobreposições de tarefas

Por padrão, as tarefas agendadas serão executadas mesmo se a instância anterior da tarefa ainda estiver em execução. Para evitar isso, você pode usar o withoutOverlappingmétodo:

$schedule->command('emails:send')->withoutOverlapping();

Neste exemplo, o emails:send comando Artisan será executado a cada minuto, se ainda não estiver em execução. O withoutOverlappingmétodo é especialmente útil se você tiver tarefas que variam drasticamente em seu tempo de execução, impedindo que você preveja exatamente quanto tempo uma determinada tarefa levará.

Modo de manutenção

As tarefas agendadas do Laravel não serão executadas quando o Laravel estiver em modo de manutenção , já que não queremos que suas tarefas interfiram em qualquer manutenção inacabada que você possa estar executando em seu servidor. No entanto, se você quiser forçar uma tarefa a ser executada mesmo no modo de manutenção, use o evenInMaintenanceModemétodo:

$schedule->command('emails:send')->evenInMaintenanceMode();

Saída de Tarefa

O planejador do Laravel fornece vários métodos convenientes para trabalhar com a saída gerada pelas tarefas planejadas. Primeiro, usando o sendOutputTométodo, você pode enviar a saída para um arquivo para inspeção posterior:

$schedule->command('emails:send')
         ->daily()
         ->sendOutputTo($filePath);

Se você gostaria de acrescentar a saída a um determinado arquivo, você pode usar o appendOutputTométodo:

$schedule->command('emails:send')
         ->daily()
         ->appendOutputTo($filePath);

Usando o emailOutputTométodo, você pode enviar por e-mail a saída para um endereço de e-mail de sua escolha. Antes de enviar por e-mail a saída de uma tarefa, você deve configurar os serviços de e-mail do Laravel :

$schedule->command('foo')
         ->daily()
         ->sendOutputTo($filePath)
         ->emailOutputTo('foo@example.com');

Nota: As emailOutputTosendOutputToappendOutputTométodos são exclusivos para o commandmétodo e não há suporte para call.

Ganchos de tarefa

Usando os métodos beforeafter, você pode especificar o código a ser executado antes e depois da conclusão da tarefa agendada:

$schedule->command('emails:send')
         ->daily()
         ->before(function () {
             // Task is about to start...
         })
         ->after(function () {
             // Task is complete...
         });

URLs de ping

Usando os métodos pingBeforethenPing, o agendador pode executar ping automaticamente em uma determinada URL antes ou depois que uma tarefa é concluída. Esse método é útil para notificar um serviço externo, como o Laravel Envoyer , de que sua tarefa agendada está iniciando ou terminou a execução:

$schedule->command('emails:send')
         ->daily()
         ->pingBefore($url)
         ->thenPing($url);

O uso do recurso pingBefore($url)ou thenPing($url)requer a biblioteca HTTP do Guzzle. Você pode adicionar o Guzzle ao seu projeto usando o gerenciador de pacotes do Composer:

composer require guzzlehttp/guzzle