Practical Laravel – Using Cron Jobs in Laravel
In this post I will try to explain what is a Cron job and show how to use them in Laravel v3 and v4.
Let’s start with the basics. A Cron job is basically a command that is scheduled to execute at some period of time or at a very specific time. What command? Well, it can be any shell command, same commands that you use in your Terminal.
What’s a good use case of a cronjob?
I would say that cleanup(files and/or DB), sending emails or executing time-consuming actions (like operating with cache) are the primary examples of cronjobs in use. For example in my latest app that I have developed on my own in few days in Laravel 3, a file sharing service, I needed to remove all records that are older than two hours and that don’t have any children records. Also I needed to remove files in the uploads folder that are older than a certain time. Cron jobs = Executing tasks at certain time or at a period of time. As far as I know a cronjob can be setup only on Unix based machines. So this will not work on Windows machines or servers.
How does this apply to Laravel applications?
Since a cron job is just some shell command that is run at a certain time, we can run Artisan commands too. In Laravel 3 custom artisan commands are called “Tasks”. To proceed with this tutorial I highly recommend you check out the documentation of Laravel tasks if you are using Laravel 3. If you are using Laravel 4 please refer to this section in the documentation : http://four.laravel.com/docs/commands and also Nettuts+ has an amazing tutorial written by Jason Lewis about Laravel 4 commands : http://net.tutsplus.com/tutorials/php/your-one-stop-guide-to-laravel-commands/
I will be using Laravel 3 for this tutorial but the concepts are pretty much the same for Laravel 4 applications.
For my example I will want to have a cron job that runs every hour to cleanup some records in the DB. Let’s say I have model “Item” and a model “Bucket”. Each bucket has many items, and I would like to remove all buckets that are empty, i.e. do not have any related “Item” in the DB.
To start with, I need to create a Laravel Artisan task and test that it works. Again, I am using Laravel 3 here so this will be different for Laravel 4.
From L3 docs :
To create a task create a new class in your application/tasks directory. The class name should be suffixed with “_Task”, and should at least have a “run” method, like this (tasks/notify.php):
Creating a task class:
class Notify_Task {
public function run($arguments)
{
// Do awesome notifying...
}
}
Or in our case :
Creating a class “Custodian” for record maintenance:
class Custodian_Task {
public function run($arguments)
{
$buckets = Bucket::all();
$cnt = 0;
foreach ( $buckets as $bucket) {
if (!$bucket->items) {
$bucket->delete();
$cnt++;
}
}
echo $cnt.' Unclaimed Buckets removed';
}
}
In this task I selected all buckets, then going through each bucket I delete all buckets that have no model “Item” associated with it.
Now to run this Laravel Artisan command I execute this in the Terminal (need to cd into application’s folder first) :
php artisan custodian
And if I have some buckets that are empty my Terminal output will be something like this:
7 Unclaimed Buckets removed
Simple? You can put anything in that task as you would put in a controller, and you get to use the awesome Eloquent or Fluent models.
Well now let’s say I want this to be a Cron job. On my server I would run the following command :
crontab -e
Which will launch a cron job manager.
Since it is opening Vi editor, you might want to look at how to operate with it: http://www.washington.edu/computing/unix/vi.html
I just type “i” to enter “insert mode” in Vi editor and start creating my cron job schedule.
Here is a cron job that will run the above mentioned Laravel artisan task once an hour :
1 * * * * /usr/bin/php /Users/me/Desktop/WebDev/projects/laravelapp/artisan custodian
Note that I referenced my laravel project and PHP by giving a full path.
After you are done typing your cron job press Escape, then “:w”, Enter, then “:q” to save your cron job and exit. Now if you run cronjob -l you should see what you typed in the cron job manager and that will mean that the cron job is ready to go and will run once an hour. I have seen instances where cron job would not run and a way to solve that can be as simple as adding a new line at the end of the cron job file. Also make sure that your command runs Ok before you put it in the cron tab. For example I ran this in the terminal to test that the command works:
/usr/bin/php /Users/me/Desktop/WebDev/projects/laravelapp/artisan custodian
And it gave me the desired output so I know that my command works.
What if you want the cronjob to run at a desired time? Well you need to know how the cron schedule works. The format of cron schedule is like this :
minute hour day month day-of-the-week command-to-run
Where :
- minute (0-59)
- hour (0-23)
- day of month (1-31)
- month (1-12)
- day of the week (0-6 starting on Sunday-0)
Each time entity can be replaced by an asterisk and that would mean to run the cron job at every minute or hour or day of month or month or day of week).
Examples :
Every hour on the 18-th minute of the hour
18 * * * *
Every hour on the 18-th minute of the hour on Tuesdays only
18 * * * 2
You can also run the cron job at an interval of time, let’s say every 15 minutes. For that you need to give this format (asterisk divide by number):
*/15 * * * *
Examples :
Run every other hour at the top of the hour (minute 0)
0 */2 * * *
Every 20 minutes of every other hour
*/20 */2 * * *
You can use this visual cron tab scheduler to easily create the needed time periods:
http://www.corntab.com/pages/crontab-gui
You can email the results of the cronjob to yourself by putting this at the top of the cron job file:
MAILTO="youremail@example.com"
And adding this to the end of your cron job :
> /dev/null 2>&1
That is all there is to it to start using cron jobs in Laravel applications. What are good examples of using Cron jobs in your applications?
Note on optimization : in the Custodian example above my query is very inefficient, imagine my buckets table grows to a million records, this would put a lot of strain on the server. Instead of selecting all items I advise to rely on created_at timestamp of the record (make sure you have proper timezone set in application.php config file in your Laravel app) and select all records older than certain time period. I use Jason Lewis’ Expressive Date package to have full control of what period of time I want to select and that way my records are efficiently selected for example only for the past two hours or past week instead of selecting all records in the DB.
Enjoy using Cron jobs!
Resources on Cronjobs :
@jasonclewis referenced your blog and Expressive Date in my latest blog post on using Cron jobs in Laravel http://t.co/N5GAxuCag6 =)
Practical Laravel – Using Cron Jobs in Laravel http://t.co/1EOdrUY1Vz
RT @msurguy: Published new post : Practical Laravel – Using Cron Jobs in #laravelphp applications http://t.co/ZAi9MDNPRR please RT
RT @msurguy: Published new post : Practical Laravel – Using Cron Jobs in #laravelphp applications http://t.co/ZAi9MDNPRR please RT
RT @msurguy: Published new post : Practical Laravel – Using Cron Jobs in #laravelphp applications http://t.co/ZAi9MDNPRR please RT
Practical Laravel – Using Cron Jobs in Laravel http://t.co/aIVqoxQDsp
Thanks for the useful info. I know I wouldn’t want a few technicalities involved in making a cron job work, keeping me from marking an important task ‘complete’ 🙂 I can just refer back to this post and I’ll have *everything* I need.
Keep writing!
Practical Laravel – Using Cron Jobs in Laravel – Maxoffsky | http://t.co/NxeOqaayjW via @kippt
One of the other useful resources is
http://www.dataphyx.com/cronsandbox/
Using Cron Jobs in #Laravel http://t.co/ymNBt6qFcc
Thanks James! Added to the list of resources!
Thanks Maksim,
Whenever i am looking for something that i don’t know, i always find it in your tutorials.
Well in my case I had to do this
/usr/bin/php5-cli /home/***/artisan cron:run
I had to track down the ph5-cli in order for this to work
Another crontab syntax generator is at http://www.easycron.com/generator/cronjob
What’s about Laravel 4? Here is queues but I am not getting anything! What is this!!!! 🙁
You can use the same technique with cron jobs in Laravel 4. The queues are only needed if you want to delay or offload the execution of the process to a later time (vs. scheduled execution).
But I read somewhere that ‘Tasks’ has being replaced by ‘Command’ or something
Yes! I just found this post and it helped me tremendously. Thank you!