Task Scheduling và Cron Job trong Laravel 5.7
Bài đăng này đã không được cập nhật trong 4 năm
Khi triển khai các ứng dụng, đôi khi chúng ta có một số tác vụ cần được chạy định kỳ trên máy chủ, điều này có nghĩa là các tác vụ sẽ được thực hiện lặp lại vào một thời điểm được chỉ định cụ thể, ví dụ như đó có thể là gửi email quảng cáo, tối ưu hóa CSDL, tạo bản sao lưu hoặc tạo báo cáo lưu lượng truy cập trang web. Những tác vụ này cần được chạy hoàn toàn tự động, do đó để tự động hóa các tác vụ này thì cần có một hệ thống Tasks Schedule (có thể hiểu là lập lịch cho các tác vụ), Laravel Cron Job cung cấp một cơ chế Task Scheduling rất linh hoạt.
Khái niệm Cron
Cron là một trình lập lịch tác vụ dựa trên thời gian trong các hệ điều hành phía server. Nó chạy các lệnh shell trong khoảng thời gian được chỉ định trước. Cron sử dụng tệp cấu hình có tên crontab còn được gọi là bảng Cron để quản lý quá trình lập lịch tác vụ. Crontab chứa tất cả các công việc Cron liên quan đến một nhiệm vụ cụ thể. Các công việc Cron bao gồm hai phần, biểu thức Cron và lệnh shell cần được chạy.
* * * * * command/to/run
Trong biểu thức Cron ở trên (* * * * *)
, mỗi trường (dấu *)
là một tùy chọn để xác định tần suất lịch biểu tác vụ. Các tùy chọn này đại diện cho phút, giờ, ngày trong tháng, tháng và ngày trong tuần theo thứ tự nhất định. Biểu tượng dấu hoa thị có nghĩa là tất cả các giá trị có thể, vì vậy lệnh trên sẽ chạy mỗi phút.
Ví dụ Cronjob bên dưới sẽ được thực thi vào mỗi lúc 6:20 sáng ngày 10 mỗi tháng.
20 6 10 * * command/to/run
Tạo Scheduled Task trong Laravel
Có nhiều cách khác nhau để chúng ta có thể định nghĩa Scheduled Tasks trong Laravel. Chúng ta hãy cùng tìm hiểu nhé.
Tạo một Artisan Command mới
php artisan make:command WordOfTheDay
Lệnh trên sẽ tạo ra một tệp lệnh mới, file WordOfTheDay.php trong thư mục app/Console/Commands. Mở file này lên chúng ta sẽ thấy các đoạn code tương tự
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class WordOfTheDay extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:name';
/**
* 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()
{
//
}
}
Thay thế command:name
thành word:day
protected $signature = 'word:day'
Thay đổi description của task cron
protected $description = 'Send a Daily email to all users with a word and its meaning'
Phương thức xử lý được gọi bất cứ khi nào lệnh được thực thi. Đây là nơi chúng ta đặt mã để thực hiện nhiệm vụ cụ thể. Trong file WordOfTheDay.php có phương thức handle và tất cả sẽ được thay đổi trong đây.
<?php
namespace App\Console\Commands;
use App\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class WordOfTheDay extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'word:day';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send a Daily email to all users with a word and its meaning';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$words = [
'aberration' => 'a state or condition markedly different from the norm',
'convivial' => 'occupied with or fond of the pleasures of good company',
'diaphanous' => 'so thin as to transmit light',
'elegy' => 'a mournful poem; a lament for the dead',
'ostensible' => 'appearing as such but not necessarily so'
];
// Finding a random word
$key = array_rand($words);
$value = $words[$key];
$users = User::all();
foreach ($users as $user) {
Mail::raw("{$key} -> {$value}", function ($mail) use ($user) {
$mail->from('info@tutsforweb.com');
$mail->to($user->email)
->subject('Word of the Day');
});
}
$this->info('Word of the Day sent to All Users');
}
}
Đăng ký Command
Sau khi tạo xong command thì chúng ta cần phải đăng ký nó trong Kernel. Mở file app/Console/Kernel.php
<?php
namespace App\Console;
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 = [
//
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Bây giờ hãy thử chạy lệnh php artisan list
trong terminal, bạn sẽ thấy command của bạn đã được đăng ký. Bạn có thể xem tên command đã đăng ký và description.
Thực thi command này trong terminal
php artisan word:day
Chúng ta cũng sẽ thấy log mesage trong terminal
Sử dụng phương thức Closure/Callback
Task schedule của Laravel cho phép chúng ta thực hiện gọi lại hoặc đóng theo định kỳ bằng phương thức gọi. Hãy thêm các đoạn mã sau vào phương thức lập lịch của app/Console/Kernel.php
. Tại đây, nội dung của lớp chỉ có phương thức lịch biểu.
<?php
namespace App\Console;
use App\User;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
User::where('spam_count', '>', 100)
->get()
->each
->delete();
})->hourly();
}
}
Mình đã đặt tần suất của task thành hàng giờ, vì vậy nó sẽ thực hiện mỗi giờ. Trong phương thức gọi, chúng ta chỉ đơn giản là loại bỏ người dùng có số lượng thư rác hơn 100.
Task Scheduler trong Laravel
Trình lập lịch tác vụ trong Laravel thực thi lệnh thủ công, shell hoặc callback định kỳ theo thời gian xác định. Để làm điều này, chúng ta sử dụng phương thức lập lịch trong app/Console/Kernel.php
như chúng ta đã thảo luận trước đó.
protected function schedule(Schedule $schedule)
{
$schedule->command('word:day')
->daily();
}
$schedule->command('word:day') là nơi chúng ta xác định lệnh nào cần được thực thi và -> Daily (); là xác định tần suất thực hiện. Có một số khoảng thời gian nữa mà chúng ta có thể xác định. Bạn có thể thay thế ->daily (); với một tùy chọn khoảng thời gian khác từ danh sách sau đây. Bạn có thể tìm hiểu thêm về Task Scheduling trong Scheduling Laravel Documentation
Starting Laravel Scheduler
Hãy thiết lập cho Cron Job tự động chạy mà không cần khởi chạy thủ công bằng cách chạy lệnh. Để tự khởi động Scheduler trong Laravel, chúng ta chỉ cần thêm một Cron Job thực thi mỗi phút. Đi đến terminal, ssh vào server của bạn, cd vào dự án của bạn và chạy lệnh sau đây:
crontab -e
Thao tác này sẽ mở file Crontab của server, dán mã bên dưới vào tệp, lưu và sau đó thoát.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Đừng quên thay thế /path/to/artisan
bằng đường dẫn đầy đủ đến Artisan Command trong ứng dụng Laravel của bạn.
All rights reserved