img
AboutContactBlogGet in touch

9 min read

Efficient Task Scheduling in Laravel: Understanding Laravel Cron Jobs

Interested in generating passive income? Join our partnership program and receive a commission on each new client referral. Learn more.

Laravel Cron is a time-based job scheduler in Unix-like operating systems. It allows for scheduling tasks to run periodically at fixed times, dates, or intervals. These tasks are managed by the cron daemon, which continuously checks the system’s crontab files for scheduled tasks and executes them accordingly.

In Laravel 11, cron jobs are defined in your application’s /routes/console.php file. The Schedule facade offers several functions to simplify task scheduling within your application.

In this blog, we’ll guide you through the fundamentals of scheduling tasks, how they work in the context of Laravel, and how you can align them for your application’s workflow. We’ll also use Laravel cron in real-world examples to demonstrate how we use it to automate various tasks within Laravel apps.

Closure-Based Tasks

Using Laravel Cron is helpful when dealing with closure-based tasks. If you need to perform quick ad-hoc tasks or when the task logic is relatively simple, using the call method will be extremely useful. It provides a straightforward way to execute custom PHP logic without the need to create separate command classes or Artisan commands. This method enables you to define a closure containing the logic you want to execute at specified intervals.

Example:

use Illuminate\Support\Facades\Schedule;

Schedule::call(function () {
    $overdueOrders = Order::isOverdue()->get();

    foreach ($overdueOrders as $order) {
        $order->update(['status' => 'overdue']);
    }
})->daily();

Note that you can also schedule invokable objects instead of closure using the call method:

Schedule::call(new UpdateOrderStatuses)->daily();

Scheduling Artisan Commands

In Laravel, you can schedule the execution of Artisan commands directly to automate various command-line tasks within your Laravel application. This integration simplifies common tasks like running database migrations, clearing caches, and generating reports.

In our projects, we often need to run a specific command at regular intervals. When faced with larger and more complex tasks, we use this method instead of the call method. It allows us to encapsulate complex tasks into Artisan commands and schedule them. Let’s take a look at an example:

use Illuminate\Support\Facades\Schedule;

// Using the command name
Schedule::command('reports:generate', ['--force'])->daily();

// Or

// Using the command class
Schedule::command(App\Console\Commands\GenerateReportsCommand::class, ['--force'])->daily();

We also schedule an Artisan command defined by a closure directly by chaining the scheduling-related methods after the command’s definition. This approach is especially useful for tasks that require on-the-fly customization or dynamic parameterization based on runtime conditions. Here’s how we used it in our project:

Artisan::command('send:reminder-emails', function () {
    $users = User::where('subscription_status', 'expired')->get();
    
    foreach ($users as $user) {
       $user->notify(new SubscriptionReminderNotification($user));
    }
})->purpose('Send reminder emails to users with expired subscriptions')->daily();

Scheduling Queued Jobs

You can schedule the execution of queued jobs using the job method provided by the Schedule facade. This method is especially useful for running background tasks asynchronously.

For example, in our project, when it came to scheduling a queued job, we used the job method. Here’s how we implemented it:

use App\Jobs\ProcessReports;
use Illuminate\Support\Facades\Schedule;

Schedule::job(new ProcessReports, 'reports', 'sqs')->daily();

In this example, we simply dispatch the ProcessReports job to the “reports” queue on the “sqs” connection.

Scheduling Shell Commands

Laravel provides a simple way to execute shell commands as scheduled tasks. The exec method allows developers to automate system-level tasks directly from your Laravel application. When there is a requirement to execute shell commands or scripts as part of our scheduled tasks, this approach is invaluable since it allows for automating tasks such as database backups, server maintenance, or external API calls. Here’s an example:

Schedule::exec('sh /path/to/backup_script.sh')->daily();

Schedule Frequency

Laravel’s task scheduler offers a range of frequency options for scheduling Laravel cron jobs, providing flexibility in defining how often tasks should be executed. These options support you in automating various aspects of your application according to your specific needs.

For instance, you can schedule tasks to run every minute, every five minutes, or at hourly intervals using methods like everyMinute(), everyFiveMinutes(), and hourly(), respectively. This granularity enables you to execute frequent tasks such as data synchronization, monitoring, or cache clearing.

Moreover, you can schedule tasks to run daily using daily(), specifying the time at which they should be executed.

For less frequent tasks, you can schedule them weekly, monthly, or yearly using weekly(), monthly(), and yearly(), respectively.

There are many more frequency options available in Laravel’s task scheduler that could meet your specific requirements. The Laravel documentation on task scheduling provides more details and a list of available options.

Running Laravel Cron Jobs

Cron jobs are defined using a specific syntax that consists of five fields:

  1. Minute (0-59): Specifies the minute of the hour when the task should run.
  2. Hour (0-23): Specifies the hour of the day when the task should run.
  3. Day of Month (1-31): Specifies the day of the month when the task should run.
  4. Month (1-12): Specifies the month of the year when the task should run.
  5. Day of Week (0-7): Specifies the day of the week when the task should run (0 or 7 represents Sunday).

Here are some examples of cron job entries:

  • * * * * command: Runs the command every minute.
  • 0 * * * * command: Runs the command at the beginning of every hour.
  • 0 0 * * * command: Runs the command once a day at midnight.
  • 0 0 * * 0 command: Runs the command once a week on Sunday at midnight.

To execute Laravel cron jobs, you need to set up a cron job on your server. Typically, you would not add a scheduler cron entry to your local development machine. Instead, you may use the schedule:work Artisan command. This command will run in the foreground and invoke the scheduler every minute until you terminate the command:

php artisan schedule:work

To execute Laravel scheduled tasks on your server, you need to set up a cron job. Simply add an entry to your server’s crontab file, specifying the path to your Laravel project and the schedule:run artisan command. For example:

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

This entry runs the Laravel scheduler every minute and executes any pending tasks.

The last part, >> /dev/null 2>&1, is responsible for redirecting the output of the scheduled tasks.

It ensures that both regular output and error messages generated by the scheduled tasks are discarded and not displayed or stored anywhere, suppressing any output from the cron job.

This is because /dev/null is a special device file in Unix-like operating systems that discards all data written to it.

In case you need to save the output of the scheduled tasks to a file instead of discarding it, instead of redirecting the output to /dev/null, you can specify the path to a file where you want to store the output.

Output And Hooks

Laravel’s task scheduler also provides output handling for scheduled tasks, which allows you to monitor task execution and handle any output generated by the tasks. There are several methods available for task output: 

// directs the task output to a specified file
Schedule::command('email:send')->daily()->sendOutputTo('/path/to/output.log');
// appends task output to the specified file instead of overwriting it
Schedule::command('email:send')->daily()->appendOutputTo('/path/to/output.log');
// sends the task output to the specified email address
Schedule::command('email:send')->daily()->emailOutputTo('example@example.com');
//  sends the task output to the specified email address only if the task fails to execute successfully
Schedule::command('email:send')->daily()->emailOutputOnFailure('example@example.com');

Similar to output, you can use task hooks to execute code before and after a scheduled task runs or based on its success or failure.

Schedule::command('emails:send')
         ->daily()
         ->before(function () {
             // execute before the task runs...
         })
         ->after(function () {
             // execute after the task runs...
         })
         ->onSuccess(function () {
             // execute if the task succeeds...
         })
         ->onFailure(function () {
             // execute if the task fails...
         });

That’s all for now, folks - keep pushing forward! And if you ever need a hand with Laravel development, just know we’re here to help. Be sure to check out our dedicated page for more details.

img

Meet the authors

We are a 200+ people agency and provide product design, software development, and creative growth marketing services to companies ranging from fresh startups to established enterprises. Our work has earned us 100+ international awards, partnerships with Laravel, Vue, Meta, and Google, and the title of Georgia’s agency of the year in 2019 and 2021.

img
Contact us