12/08/2018, 16:32

Quản lý Cronjobs với Laravel

Bài dịch từ trang developer.telerik.com Đôi khi ứng dụng của bạn cần chạy các nhiệm vụ quản trị theo định kỳ trên máy chủ. Cho dù bạn muốn gửi email cho người dùng của mình hoặc clean database tables vào cuối ngày, bạn sẽ cần một cơ chế lập lịch trình nhiệm vụ để làm các việc đó. Cron là một ...

Bài dịch từ trang developer.telerik.com

Đôi khi ứng dụng của bạn cần chạy các nhiệm vụ quản trị theo định kỳ trên máy chủ. Cho dù bạn muốn gửi email cho người dùng của mình hoặc clean database tables vào cuối ngày, bạn sẽ cần một cơ chế lập lịch trình nhiệm vụ để làm các việc đó. Cron là một chương trình lập lịch nhiệm vụ trong các hệ thống unix, chạy các shell commands trong một khoảng thời gian nhất định. Bài viết này không nhằm giới thiệu về Cron, nhưng vì nó là một khái niệm quan trọng trong hướng dẫn của chúng tôi, chúng tôi sẽ mô tả các khái niệm cơ bản về cách hoạt động.

Cron là một trình nền lập lịch nhiệm vụ được lên lịch trước và thực hiện ở những khoảng thời gian nhất định. Cron sử dụng một tập tin cấu hình gọi là crontab, còn được gọi là bảng cron, để quản lý tiến trình lập kế hoạch. Crontab chứa các công việc cron, mỗi liên quan đến một nhiệm vụ cụ thể. Các công việc của Cron gồm có hai phần, biểu thức cron và lệnh shell được chạy:

* * * * * command/to/run

Mỗi trường trong biểu thức ở trên (* * * * *) là một lựa chọn để thiết lập tần suất biểu đồ. Nó bao gồm phút, giờ, ngày trong tháng, tháng và ngày trong tuần theo thứ tự của vị trí. Biểu tượng dấu hoa thị đề cập đến tất cả các giá trị có thể cho trường tương ứng. Kết quả là, công việc cron trên sẽ được chạy mỗi phút trong ngày. Công việc cron sau được thực hiện vào lúc 12 giờ 30 mỗi ngày:

30 12 * * * command/to/run

Đây chỉ là nổi của tảng băng trôi Cron; để tìm hiểu thêm về nó, bạn có thể muốn truy cập vào trang wikipedia.

Trong các ứng dụng được hỗ trợ PHP, các tác vụ quản trị thường là các tập lệnh PHP độc lập được chạy trong chế độ CLI. Các kịch bản được viết để thực hiện các công việc khác nhau vào những thời điểm nhất định. Tuy nhiên, chúng ta không xây dựng cron một cách hiệu quả mà không có sức mạnh của các thư viện PHP và các frameworks. Trong bài này, bạn sẽ học cách sử dụng khuôn khổ Laravel để tạo các kịch bản PHP mạnh mẽ cho dòng lệnh và lập kế hoạch ngay từ mã nguồn.

Việc tạo ra một command trong PHP cũng đơn giản như tạo ra một PHP script, sau đó chạy nó trong dòng lệnh bằng cách sử dụng lệnh php:

php somefile.php

Như bạn thấy, tệp tin được truyền như một đối số cho lệnh php. Cho dù ứng dụng của bạn đã được phát triển ở Laravel hay bạn chỉ muốn sử dụng facades và helpers để tạo ra các tập lệnh của mình, bạn sẽ cần phải khởi động Laravel trước khi sử dụng nó. Tuy nhiên, có một sự thay thế tốt hơn cho việc này: tạo một lệnh Laravel Artisan. Khi sử dụng lệnh của Artisan, chúng ta sẽ có quyền truy cập vào tất cả các tính năng của Laravel, bao gồm helpers, facades và các lệnh Artisan khác.

Chúng tôi sử dụng make: console Artisan lệnh để tạo ra một bộ khung. Ví dụ: chúng tôi sẽ tạo một lệnh gửi tin nhắn SMS chúc mừng đến người dùng của chúng tôi vào ngày sinh nhật của họ.

$ php artisan make:console HappyBirthday --command=sms:birthday

Lệnh trên sẽ tạo một class có tên HappyBirthday trong một tệp có cùng tên trong thư mục app / Console / Commands. Chúng tôi cũng chọn tên cho lệnh thông qua tùy chọn lệnh. Đây là tên mà chúng ta sẽ sử dụng khi gọi lệnh. Bây giờ chúng ta hãy mở tập tin, và xem những gì chúng tôi có. Có một số thuộc tính và phương pháp bên trong lớp đã được xây dựng sẵn:

<?php
namespace AppConsoleCommands;

use IlluminateConsoleCommand;

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

    /**
     * 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()
    {
        //
    }
}

Đối với $$escription, chúng ta có thể đặt một mô tả đơn giản về những gì mà lệnh thực hiện khi thực hiện.

protected $description = 'Sends a Happy birthday message to users via SMS';

Trong Laravel, bất cứ khi nào một lệnh được thực thi trong terminal, phương thức handle của class lệnh được gọi. Đó là nơi chúng ta viết code logic. Trong trường hợp của chúng ta, để gửi một thông báo sinh nhật cho người dùng vào ngày sinh nhật của họ, chúng tôi có thể sửa đổi phương pháp xử lý như sau:

<?php
// ...
public function handle()
{
  User::whereBirthDate(date('m/d'))->get(); 

  foreach( $users as $user ) {
    if($user->has('cellphone')) {
    SMS::to($user->cellphone)
       ->msg('Dear ' . $user->fname . ', I wish you a happy birthday!')
       ->send();
    }   
}  

$this->info('The happy birthday messages were sent successfully!');

}

Chúng ta cũng cần phải đăng ký nó với Artisan, để nó có sẵn trong terminal. Để thực hiện việc này, chúng ta chỉ cần thêm lệnh của tên lớp vào mảng lệnh của lớp Kernel, được đặt tại app/Console/Kernel.php.

<?php
class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        // ...
        'AppConsoleCommandHappyBirthday'
    ];

    // ...

Nếu chúng ta gõ php artisan trong terminal, chúng ta sẽ thấy chú thích command của chúng ta.

$ php artisan list

sms
  sms:birthday        Sends a Happy birthday to users via SMS

Điều này sẽ giúp chúng ta phân loại chúng dựa trên cách sử dụng chúng. Kết quả là, bất cứ khi nào chúng ta chạy lệnh trong terminal, một thông báo sinh nhật vui vẻ sẽ được gửi đến nhóm người dùng:

$ php artisan sms:birthday

The happy birthday messages were sent successfully!

Đến phần thú vị. Chúng ta hãy lên kế hoạch cho một nhiệm vụ để chạy lệnh mà chúng ta vừa xây dựng. Để thực hiện việc này, chúng ta sẽ sử dụng một tính năng mà bạn sẽ yêu thích: Laravel Task Scheduler. Các tasks được xác định bên trong phương thức schedule của lớp Kernel. Chúng ta có thể thêm nhiều lệnh Artisan như chúng ta cần bằng cách sử dụng phương thức command. Nhiệm vụ của chúng tôi, theo cách sử dụng của nó, được cho là chạy một lần mỗi ngày. Vì vậy, chúng ta có thể sử dụng phương pháp daily () như sau:

<?php

// ...
protected function schedule(Schedule $schedule)
{   
        $schedule->command('sms:birthday')->daily();
}

Chúng ta có thể lên lịch cho tất cả các lệnh ngay từ phương thức schedule. Như tài liệu hướng dẫn, có rất nhiều tần số lịch trình mà chúng tôi có thể chỉ định cho các nhiệm vụ. Chúng tôi sẽ liệt kê một số trong số chúng ở đây nhưng bạn có thể muốn đọc tài liệu để xem danh sách đầy đủ và quyết định phù hợp nhất với trường hợp của bạn.

Để chạy một nhiệm vụ mỗi giờ mỗi ngày

<?php
$schedule->command('myTask')
         ->hourly(); 

Để chạy một nhiệm vụ mỗi ngày vào lúc nửa đêm:

<?php
$schedule->command('myTask')
         ->daily(); 

Để chạy một nhiệm vụ mỗi ngày vào lúc 9:30:

<?php
$schedule->command('myTask')
         ->dailyAt('09:30'); 

Để chạy một nhiệm vụ mỗi tuần:

<?php
$schedule->command('myTask')
         ->weekly(); 

Để chạy nó mỗi tháng:

<?php
$schedule->command('myTask')
         ->monthly(); 

Chúng ta cũng có thể sử dụng cron schedule tuỳ chỉnh, giống như một biểu thức công việc cron thông thường:

$schedule->command('myTask')
         ->cron('* * * * *');

Nhiệm vụ trên sẽ được thực hiện mỗi phút.

Laravel cũng cung cấp một tập các ràng buộc thời gian, có thể được kết hợp với các phương pháp trên. Ví dụ: chúng tôi có thể lên lịch cho một tác vụ được chạy hàng tuần, nhưng giới hạn thời gian cho một ngày và giờ nhất định.

<?php
$schedule->command('theTask')
         ->weekly()
         ->mondays()
         ->at(12:30); 

hoặc

<?php
$schedule->command('theTask')
         ->weekly()
         ->sundays() 

Chúng ta có thể đi xa hơn và hạn chế việc thực hiện các nhiệm vụ đến một điều kiện nhất định, bằng cách sử dụng phương thức when với closure. Tác vụ sẽ được thực hiện chỉ khi closure trả về true.

<?php
$schedule->command('table:clean')
          ->daily()
          ->when(function() {
             return SMS::isWorkingFine();
          });

Để bắt đầu chương trình lập lịch, chúng ta chỉ cần thêm một công việc cron trên máy chủ (sử dụng crontab -e command), thực hiện các tiến trình php /path/to/artisan:run mỗi phút trong ngày:

* * * * * php /path/to/artisan schedule:run 1>> /dev/null 2>&1

Xin lưu ý rằng bạn cần phải cung cấp đường dẫn đầy đủ cho lệnh của Artisan command. Để loại bỏ kết cron output chúng ta đặt / dev / null 2> & 1 vào cuối biểu thức cronjob.

0