Task Scheduling and Cron Jobs in Laravel

Task Scheduling and Cron Jobs in Laravel

Have you ever tried to set up a cron job using PHP?

If yes, then you know the pain of managing it. Laravel provides a very intuitive and simple way to manage all your tasks and cron jobs. In this post, I’m going to show you how you can create scheduled tasks in Laravel and set up a cron job on the server to run all your tasks.

A scheduled task is a task defined by you and run by the server at a predefined time. When you run a web application or even mobile application, you have to define some tasks which run in the background without interrupting your application. Such as for an e-commerce application, you might want to set up a task to send order completion email to users whose orders are successfully processed.

Another example could be for SAAS (Software As A Service) application, you might want to send notifications to all users whose subscription is about to expire. There is endless usage of task scheduling.

The main use of cron job is updating database records, sending emails, generating reports and executing time-consuming tasks behind the scene.

We achieve all such tasks by Laravel Task Scheduler. Now let’s start and create a task and scheduled it.

Creating a New Task

For our example I will assume, we want to delete all orders from the database which are pending. For that, we will generate a new artisan command which will delete all pending orders daily.

We will generate a console command by running below the artisan command.

php artisan make:command ClearPendingOrderCommand

Above command will generate a class file in app/Console/Commands folder of your Laravel application.

If you want to predefine the terminal command name while generating you can pass command argument after the name.

php artisan make:command ClearPendingOrderCommand --command=clear:orders

Your new command class ClearPendingOrderCommand will look like this.

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ClearPendingOrderCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'clear:orders';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
    }
}

You can find in the above class that $signature which defines the terminal command name and $description which define the description which helps to provide more information about the command.

Now we need to register our command in the Kernel class which is located at app/Console. Just update the $commands property in Kernel.php file with below.

protected $commands = [
        'App\Console\Commands\ClearPendingOrderCommand',
    ];

Now you command is registered and will be available in the artisan commands list if you run below:

php artisan list

Write a Script for the Task

Whenever, you run php artisan clear:orders, handle() method within your command class will be called when the task is scheduled to execute. As we need to delete all pending orders will will update our command class with below:

namespace App\Console\Commands;

use App\Order;
use Illuminate\Console\Command;

class ClearPendingOrderCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'clear:orders';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Delete all pending orders.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        Order::where('status', 'pending')->delete();
        $this->info('All pending orders are deleted successfully!');
    }
}

Scheduling the Task

Laravel scheduler provides a rich library to define the schedules in Laravel. All task schedules are defined in app/Console/Kernal‘s schedule(Schedule $schedule) method.

We can define all our tasks which need to be scheduled in this method. So let’s add our task to this method and set it to run daily.

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

This is a new way of wrapping your cron jobs in PHP way within your application. Above code snippet is just a wrapper around Linux cron jobs and we set it up right within our application.

In the above code, we can see that schedule() function accept a type hinted instance of the Schedule class. Then in the body of the schedule() function, we are able to define a schedule to fire artisan command.

Running Linux Terminal Commands

In addition to running artisan commands, you can also run Linux terminal command as well right within your application using exec() method. For example, in below command, we are moving to the directory and list the content of a directory and sending output to a text file.

/**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->exec('cd ~/var/www/html/larashout && ls')
                ->sendOutputTo('/home/larashout/log.txt')
                ->everyMinute();
    }

Other Laravel Scheduler Methods

Laravel scheduler provides many methods which map to a cron job timing, some of them are below which I have used a lot.

  • ->everyMinute(); : Run the task every minute
  • ->everyFiveMinutes(); : Run the task every five minutes
  • ->hourly(); : Run the task every hour
  • ->hourlyAt(15); : Run the task every hour at 15 mins past the hour
  • ->daily(); : Run the task every day at midnight
  • ->dailyAt('15:00'); : Run the task every day at 15:00
  • ->weekly(); : Run the task every week
  • ->monthly(); : Run the task every month

Learn More

There are other methods available as well, I suggest you to have a look on Laravel Scheduling documentation.

Starting the scheduler on your server

In order to start Laravel Scheduler, we need to add a cron entry to our server. All cron jobs entries are stored in a file called crontab. If you ssh to your server and run crontab -l, you will be able to see all crons which are currently running. Usually, this file is empty.

To add a new cron job entry, edit the file and add below on a new line.

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

Warning

Please change path-to-your-laravel-project with your laravel application path.

After setting up the schedule, all pending orders will be removed from the database daily.

Conclusion

Laravel Scheduler is a great utility to set up some routine tasks. It provides the ability to focus on writing commands based logic and Laravel will take care of the rest.

If you have any suggestion or question regarding this post, please leave them in the comment box below.

Your little help will keep this site alive and help us to produce quality content for you.