Vietnamese (Tiếng Việt) translation by Thai An (you can also view the original English article)
Trong bài này, chúng ta sẽ thảo luận chi tiết một trong những tính năng thú vị của framework web Laravel web - lập lịch trình cho công việc. Xuyên suốt bài viết này, chúng ta sẽ xem xét làm thế nào Laravel cho phép bạn quản lý các công vụ đã lên lịch trình trong ứng dụng của bạn. Hơn nữa, chúng tôi cũng sẽ thực hiện việc tạo các công vụ được lên lịch trình nhằm mục đích minh hoạ.
Framework Laravel cho phép bạn thiết lập các nhiệm vụ theo lịch trình để bạn không phải lo lắng về việc thiết lập chúng ở cấp độ hệ thống. Bạn có thể từ bỏ cú pháp cron phức tạp trong khi thiết lập các nhiệm vụ theo lịch trình khi Laravel cho phép bạn định nghĩa chúng theo một cách thân thiện với người sử dụng.
Chúng tôi sẽ bắt đầu bài viết với cách bạn được sử dụng để thiết lập các công việc cron truyền thống và sau đó chúng tôi sẽ khám phá cách Laravel đạt được nó. Trong nửa sau của bài viết, chúng tôi sẽ thử nghiệm bằng cách tạo ra một số nhiệm vụ được lên lịch tùy chỉnh để cung cấp thông tin chi tiết về chủ đề.
Thiết lập truyền thống cho tác vụ đã lên lịch
Trong phát triển ứng dụng hàng ngày của bạn, bạn thường phải đối mặt với tình huống đòi hỏi bạn thực hiện một số script hoặc command (lệnh) định kỳ. Nếu bạn đang làm việc với hệ thống *nix, có lẽ bạn biết rằng các cron job đảm nhận các lệnh này. Mặt khác, chúng được gọi là nhiệm vụ đã được lên lịch trình trên các hệ thống trên nền tảng Windows.
Chúng ta hãy cùng xem xét một ví dụ đơn giản về cron job ở trên *nix.
1 |
*/5 * * * * /web/statistics.sh |
Khá đơn giản - nó chạy file statistics.sh
sau mỗi năm phút!
Mặc dù là một trường hợp sử dụng khá đơn giản, nhưng bạn thường gặp phải hoản cảnh yêu cầu bạn triển khai nhiều trường hợp sử dụng phức tạp hơn. Mặt khác, một hệ thống phức tạp đòi hỏi bạn phải định nghĩa nhiều cron jon thực thi ở các khoảng thời gian khác nhau.
Hãy xem một số nhiệm vụ mà một ứng dụng web phức tạp phải thực hiện định kỳ trong back-end.
- Dọn dẹp các dữ liệu không cần thiết từ cơ sở dữ liệu back-end.
- Cập nhật các chỉ mục bộ nhớ cache của giao diện người dùng để giữ cho nó luôn cập nhật.
- Tính toán thống kê trang web.
- Gửi email.
- Sao lưu các phần tử khác nhau của trang web.
- Phát sinh các báo cáo.
- Và hơn thế nữa.
Vì vậy, như bạn có thể thấy, có rất nhiều công vụ ở đấy chờ để được vận hành theo định kỳ và tại các khoảng thời gian khác nhau. Nếu bạn là một quản trị viên có kinh nghiệm, đó là cuộc dạo bộ để bạn định nghĩa các công việc cron cho tất cả các công việc này, nhưng đôi khi chúng ta như các nhà phát triển muốn rằng có một cách dễ dàng hơn xung quanh.
May mắn thay, Laravel xây dựng một API tích hợp sẵn để lập kế hoạch công việc cho phép bạn định nghĩa các tác vụ theo lịch trình. Và vâng, phần tiếp theo nói tất cả về điều đó - những điều cơ bản của việc lập kế hoạch công việc của Laravel.
Phương pháp của Laravel
Trong phần trước, chúng tôi đã đi qua cách thức truyền thống để thiết lập các cron job. Trong phần này, chúng ta sẽ xem xét tỉ mĩ các chi tiết cụ thể của Laravel trong ngữ cảnh của API lập kế hoạch công việc.
Trước khi chúng tôi tiếp tục, điều quan trọng cần hiểu là tính năng lập kế hoạch cung cấp bởi Laravel giống như bất kỳ tính năng nào khác và sẽ không được kích hoạt tự động. Vì vậy, nếu bạn nghĩ rằng bạn không cần phải làm bất cứ điều gì ở mức độ hệ thống thì tôi nói bạn sẽ gặp nhiều khó khăn đấy.
Trong thực tế, điều đầu tiên bạn nên làm nếu bạn muốn sử dụng hệ thống lập kế hoạch Laravel là thiết lập cron job để thực thi mỗi phút và gọi lệnh artisan được hiển thị trong đoạn mã dưới đây.
1 |
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1 |
Lệnh artisan nói trên gọi trình lên lịch Laravel, và do đó thực hiện tất cả các công việc cron đang chờ giải quyết, những cron job này được xác định trong ứng dụng của bạn.
Tất nhiên, chúng ta vẫn chưa biết làm thế nào để xác định các nhiệm vụ theo lịch trình trong ứng dụng Laravel của bạn, và đó là điều tiếp theo chúng ta sẽ đi sâu tìm hiểu.
Đó là phương thức schedule
của lớp App\Console\Kernel
mà bạn cần sử dụng nếu bạn muốn xác định các tác vụ theo lịch trình cụ thể theo từng ứng dụng.
Tiếp tục chọn nội dung của file app/Console/Kernel.php
.
1 |
<?php namespace App\Console; |
2 |
use Illuminate\Console\Scheduling\Schedule; |
3 |
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; |
4 |
|
5 |
class Kernel extends ConsoleKernel { |
6 |
/**
|
7 |
* The Artisan commands provided by your application.
|
8 |
*
|
9 |
* @var array
|
10 |
*/
|
11 |
protected $commands = [ |
12 |
'App\Console\Commands\Inspire', |
13 |
];
|
14 |
|
15 |
/**
|
16 |
* Define the application's command schedule.
|
17 |
*
|
18 |
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
19 |
* @return void
|
20 |
*/
|
21 |
protected function schedule(Schedule $schedule) |
22 |
{
|
23 |
$schedule->command('inspire')->hourly(); |
24 |
}
|
25 |
}
|
Như bạn thấy, mã lõi cung cấp một ví dụ hữu ích. Trong ví dụ trên, Laravel chạy theo lệnh inspire
của artisan tạo ra hàng giờ. Bạn không nghĩ rằng cú pháp như vậy là trực quan ở nơi đầu tiên?
Trong thực tế, có một vài cách khác nhau trong đó Laravel cho phép bạn xác định nhiệm vụ lịch:
- Sử dụng closure/callable.
- Gọi lệnh artisan.
- Thực hiện lệnh shell.
Hơn nữa, có rất nhiều tần suất lập lịch trình tích hợp sẵn có thể chọn:
- mỗi phút hoặc mỗi năm phút
- mỗi giờ/mỗi ngày/mỗi tuần/mỗi quý/mỗi năm
- tại một thời điểm cụ thể trong ngày
- và nhiều nữa
Trong thực tế, tôi sẽ nói rằng nó cung cấp một bộ đầy đủ các routine để bạn không bao giờ cần phải đụng đến shell để tạo ra cron job tuỳ biến của bạn!
Vâng, tôi có thể nói rằng bạn rất háo hức biết làm thế nào để thực hiện nhiệm vụ theo lịch trình tùy biến của bạn, và đó là những gì tôi cũng hứa ở đầu bài viết.
Tạo nhiệm vụ theo lịch trình đầu tiên của bạn trong Laravel
Như chúng ta đã thảo luận, có nhiều cách khác nhau trong đó Laravel cho phép bạn xác định các nhiệm vụ theo lịch trình. Chúng ta hãy điểm qua từng cái để hiểu nó hoạt động ra sao.
Phương thức Closure/Callable
API lập kế hoạch cung cấp phương thức call
cho phép bạn thực hiện hàm callable hoặc closure. Chúng ta hãy sửa lại file app/Console/Kernel.php
với đoạn mã sau.
1 |
<?php
|
2 |
namespace App\Console; |
3 |
|
4 |
use Illuminate\Support\Facades\DB; |
5 |
use Illuminate\Console\Scheduling\Schedule; |
6 |
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; |
7 |
|
8 |
class Kernel extends ConsoleKernel |
9 |
{
|
10 |
/**
|
11 |
* Define the application's command schedule.
|
12 |
*
|
13 |
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
14 |
* @return void
|
15 |
*/
|
16 |
protected function schedule(Schedule $schedule) |
17 |
{
|
18 |
// the call method
|
19 |
$schedule->call(function () { |
20 |
$posts = DB::table('posts') |
21 |
->select('user_id', DB::raw('count(*) as total_posts')) |
22 |
->groupBy('user_id') |
23 |
->get(); |
24 |
|
25 |
foreach($posts as $post) |
26 |
{
|
27 |
DB::table('users_statistics') |
28 |
->where('user_id', $post->user_id) |
29 |
->update(['total_posts' => $post->total_posts]); |
30 |
}
|
31 |
})->everyThirtyMinutes(); |
32 |
}
|
33 |
}
|
Như bạn thấy, chúng ta đã truyền chức năng closure đối số đầu tiên của phương thức call
. Ngoài ra, chúng tôi đã frequency suất thành mỗi 30 phút, vì vậy nó sẽ thực hiện chức năng closure mỗi 30 phút!
Trong ví dụ của chúng tôi, chúng tôi tính tổng số bài đăng trên mỗi người dùng và cập nhật bảng thống kê cho phù hợp.
Lệnh artisan
Tách biệt khỏi closure hoặc callables, bạn cũng có thể lên lịch một lệnh artisan sẽ được thực hiện trong khoảng thời gian nhất định. Trên thực tế, đó nên là cách tiếp cận được ưa thích hơn closures vì nó cung cấp việc tổ chức code tốt hơn và khả năng tái sử dụng cùng một lúc.
Tiếp tục và chỉnh sửa nội dung của file app/Console/Kernel.php
với những phần sau.
1 |
<?php
|
2 |
namespace App\Console; |
3 |
|
4 |
use Illuminate\Support\Facades\Config; |
5 |
use Illuminate\Console\Scheduling\Schedule; |
6 |
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; |
7 |
|
8 |
class Kernel extends ConsoleKernel |
9 |
{
|
10 |
/**
|
11 |
* The Artisan commands provided by your application.
|
12 |
*
|
13 |
* @var array
|
14 |
*/
|
15 |
protected $commands = [ |
16 |
'App\Console\Commands\UserStatistics'
|
17 |
];
|
18 |
|
19 |
/**
|
20 |
* Define the application's command schedule.
|
21 |
*
|
22 |
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
23 |
* @return void
|
24 |
*/
|
25 |
protected function schedule(Schedule $schedule) |
26 |
{
|
27 |
// artisan command method
|
28 |
$schedule->command('statistics:user')->everyThirtyMinutes(); |
29 |
}
|
30 |
|
31 |
/**
|
32 |
* Register the Closure based commands for the application.
|
33 |
*
|
34 |
* @return void
|
35 |
*/
|
36 |
protected function commands() |
37 |
{
|
38 |
require base_path('routes/console.php'); |
39 |
}
|
40 |
}
|
Đây là phương thức command
mà bạn muốn sử dụng nếu bạn muốn lập lịch trình một lệnh artisan giống như trong đoạn code ở trên. Bạn cần truyền signature của lệnh artisan là đối số đầu tiên của phương thức command
.
Tất nhiên, bạn cũng cần phải xác định các lệnh artisan tương ứng tại app/Console/Commands/UserStatistics.php
.
1 |
<?php
|
2 |
namespace App\Console\Commands; |
3 |
|
4 |
use Illuminate\Console\Command; |
5 |
use Illuminate\Support\Facades\DB; |
6 |
|
7 |
class UserStatistics extends Command |
8 |
{
|
9 |
/**
|
10 |
* The name and signature of the console command.
|
11 |
*
|
12 |
* @var string
|
13 |
*/
|
14 |
protected $signature = 'statistics:user'; |
15 |
|
16 |
/**
|
17 |
* The console command description.
|
18 |
*
|
19 |
* @var string
|
20 |
*/
|
21 |
protected $description = 'Update user statistics'; |
22 |
|
23 |
/**
|
24 |
* Create a new command instance.
|
25 |
*
|
26 |
* @return void
|
27 |
*/
|
28 |
public function __construct() |
29 |
{
|
30 |
parent::__construct(); |
31 |
}
|
32 |
|
33 |
/**
|
34 |
* Execute the console command.
|
35 |
*
|
36 |
* @return mixed
|
37 |
*/
|
38 |
public function handle() |
39 |
{
|
40 |
// calculate new statistics
|
41 |
$posts = DB::table('posts') |
42 |
->select('user_id', DB::raw('count(*) as total_posts')) |
43 |
->groupBy('user_id') |
44 |
->get(); |
45 |
|
46 |
// update statistics table
|
47 |
foreach($posts as $post) |
48 |
{
|
49 |
DB::table('users_statistics') |
50 |
->where('user_id', $post->user_id) |
51 |
->update(['total_posts' => $post->total_posts]); |
52 |
}
|
53 |
}
|
54 |
}
|
Câu lệnh Exec
Chúng ta có thể nói rằng các phương thức chúng tôi đã thảo luận đến giờ khá là cụ thể cho chính dụng Laravel. Hơn nữa, Laravel cũng cho phép bạn lập lịch các lệnh trình shell để bạn cũng có thể chạy các ứng dụng bên ngoài.
Chúng ta hãy xem xét nhanh một ví dụ minh họa cách sao lưu database của bạn mỗi ngày.
1 |
<?php
|
2 |
namespace App\Console; |
3 |
|
4 |
use Illuminate\Console\Scheduling\Schedule; |
5 |
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; |
6 |
|
7 |
class Kernel extends ConsoleKernel |
8 |
{
|
9 |
/**
|
10 |
* Define the application's command schedule.
|
11 |
*
|
12 |
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
13 |
* @return void
|
14 |
*/
|
15 |
protected function schedule(Schedule $schedule) |
16 |
{
|
17 |
// exec method
|
18 |
$host = config('database.connections.mysql.host'); |
19 |
$username = config('database.connections.mysql.username'); |
20 |
$password = config('database.connections.mysql.password'); |
21 |
$database = config('database.connections.mysql.database'); |
22 |
|
23 |
$schedule->exec("mysqldump -h {$host} -u {$username} -p{$password} {$database}") |
24 |
->daily() |
25 |
->sendOutputTo('/backups/daily_backup.sql'); |
26 |
}
|
27 |
}
|
Nó khá rõ ràng từ code mà bạn cần phải để sử dụng phương thức exec
của trình lên lịch, và bạn cần phải đưa câu lệnh mà bạn muốn chạy như là đối số đầu tiên của nó.
Ngoài ra, chúng tôi cũng đã sử dụng phương thức sendOutputTo
cho phép bạn thu thập kết quả của câu lệnh. Mặt khác, có một phương pháp, emailOutputTo
, cho phép bạn gửi email nội dung của kết quả thu được!
Và chúng ta đã đi đến tới cuối bài viết. Trên thực tế, chúng tôi vừa mới khai triển bề nổi của API lập kế hoạch của Laravel, và vẫn còn rất nhiều đề xuất từ API này.
Tổng kết
Hôm nay, chúng tôi đã nghiên cứu API lập kế hoạch cho nhiệm vụ trong framework web Laravel. Thật hấp dẫn khi thấy nó dễ dàng như thế nào để giúp bạn quản lý những nhiệm vụ cần phải chạy theo định kỳ.
Ở đầu bài viết, chúng tôi đã thảo luận cách truyền thống để thiết lập các nhiệm vụ theo lịch trình và sau đó chúng tôi đã giới thiệu cách Laravel thực hiện nó. Trong nửa sau của bài viết, chúng tôi đã đi qua một vài ví dụ thực tế để mô tả các khái niệm lập kế hoạch cho nhiệm vụ.
Tôi hy vọng rằng bạn đã thích bài viết này, và bạn sẽ cảm thấy tự tin hơn về việc thiết lập các nhiệm vụ theo lịch trình trong Laravel. Đối với những người bạn vừa mới bắt đầu với Laravel hoặc muốn mở rộng kiến thức, trang web hoặc ứng dụng của bạn với các phần mở rộng, chúng tôi có nhiều thứ bạn có thể học tại Envato Market.
Nên có bất cứ điều gì xuất hiện trong tâm trí của bạn, hãy bắt đầu trò chuyện bằng cách sử dụng feed dưới đây!