12/08/2018, 16:21

Create A Custom Artisan Command Laravel 5.5

Xin chào các bạn, hôm nay mình lại tiếp tục giới thiệu một phần về Laravel 5.5 - phiên bản mới nhất cho đến thời điểm hiện tại. Artisan Console thực ra không được cải tiến so với những phiên bản trước, nhưng nó cũng là một phần quan trọng luôn được list trong "Digging Deeper" của Laravel ...

Xin chào các bạn, hôm nay mình lại tiếp tục giới thiệu một phần về Laravel 5.5 - phiên bản mới nhất cho đến thời điểm hiện tại. Artisan Console thực ra không được cải tiến so với những phiên bản trước, nhưng nó cũng là một phần quan trọng luôn được list trong "Digging Deeper" của Laravel Document. Có thể nhiều bạn mới làm quen với Laravel thì sẽ không hiểu tại sao lại gõ mấy lệnh php artisan ... thì hi vọng đọc bài viết này các bạn sẽ hiểu hơn và tự tạo cho mình một console command (artisan) và chạy thử xem nó thú vị thế nào nhé!

Laravel có một giao diện dòng lệnh có tên là Artisan. Giao diện này cung cấp cho developer bọn mình rất nhiều lệnh hữu ích giúp tăng tốc độ phát triển phần mềm. Các bạn có thể xem những lệnh có sẵn mà Artisan cung cấp bằng cách gõ:

php artisan list

Mỗi một command thì lại có một màn hình "help" để hiển thị và miêu tả các các arguments (tham số) và options (tùy chọn) để các bạn dễ dàng thao tác với chúng. Lệnh để mở màn hình help này rất đơn giản, chỉ cần thêm help vào trước tên lệnh bạn muốn lấy, ví dụ như:

php artisan help make:auth

hoặc là php artisan make:auth -h (php artisan make:auth --help) Dòng lệnh này mọi người có thấy quen thuộc không ạ php artisan tinker. Mọi ứng dụng laravel đều bao gồm tinker, nó là 1 REPL (Read Eval Print Loop), cho phép bạn tương tác với toàn bộ ứng dụng thông qua dòng lệnh, nhất là thực hiện mấy câu truy vấn, jobs, events, ... Hơn thế nữa các bạn có thể mở rộng artisan bằng những lệnh của riêng bạn tạo ra và tự động hóa một số tác vụ trong ứng dụng của bạn. Nó rất hữu ích!

Tạo Command

Laravel giúp bạn làm mọi việc trở nên dễ dàng hơn, nó đã tích hơn sẵn lệnh make:command để tạo một Artisan Command. Lệnh này sẽ tạo một command class đặt trong đường dẫn app/Console/Commands. Nếu bạn mở ứng dụng mà chưa thấy đường dẫn này thì cũng đừng lo lắng, vì nó sẽ được tạo ra lần đầu tiên khi bạn chạy lệnh make:conmmand. Ví dụ dưới đây:

php artisan make:command UpdatePublishTime

UpdatePublishTime chính là tên của command class. Mục đích ở ví dụ này của mình chỉ đơn giản là update cột publish_time trong table posts của mình.

Cấu trúc Command class

Sau khi chạy lệnh trên thì các bạn mở file UpdatePublishTime.php ra các bạn sẽ thấy cấu trúc một command class như sau:

<?php

namespace AppConsoleCommands;

use IlluminateConsoleCommand;

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

Sau khi tạo xong như thế này rồi thì các bạn hãy điền thông tin vào các thuộc tính signature và description của class, nó sẽ được sử dụng khi hiển thị lệnh của bạn trên màn hình list. Còn hàm handle() sẽ được gọi mỗi khi command của bạn được thực hiện. Thế nên có xử lý logic gì thì cứ cho hết vào hàm này là oke.

Xử lý logic trong command class

Ở đây mình sẽ sửa lại class của mình như sau:

namespace AppConsoleCommands;

use IlluminateConsoleCommand;
use IlluminateSupportFacadesDB;

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Update publish time column';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        try {
            DB::beginTransaction();
          
            //update publish_time column
            DB::table('posts')->update([
                'publish_time' => '2020-12-31 00:00:00',
            ]);
            
            DB::commit();
           
            //send output to the console
            $this->info('Success!');
        } catch (Exception $e) {
            DB::rollBack();
            
            $this->error($e->getMessage());
        }
    }
}

Ở đoạn code trên, sau khi update thành công mình sẽ đưa ra các message thông báo trên giao diện command như là: line, info, comment, error, question. Mỗi một phương thức sẽ sử dụng các màu tương ứng với mục đích của chúng, ví dụ như info sẽ in ra text xanh, error là text đỏ, line thì không xét màu. Hoặc là bạn cũng có thể đưa ra một table chứa nội dung bạn vừa update như sau:

$headers = ['Name', 'Publish Time'];
$posts = AppPost::all(['name', 'publish_time'])->toArray();

$this->table($headers, $posts);

Ngoài ra các bạn còn có thể đưa ra giao diện command các nhắc nhở cho đầu vào như là một câu hỏi:

// Stop execution and ask a question 
$answer = $this->ask('What is your name?');

Câu hỏi mà người dùng không nhìn thấy nội dung mình nhập:

// Ask for sensitive information
$password = $this->secret('What is the password?');

Câu hỏi lựa chọn:

// Choices
$name = $this->choice('What is your name?', ['Trang', 'Boo'], $default);

Câu hỏi cần confirm yes/no:

// Confirmation
if ($this->confirm('Is '.$name.' correct, do you wish to continue? [y|N]')) {
//
}

Arguments và Options

Vẫn ví dụ trên, nếu như sau này bạn lại muốn update cột dữ liệu đó về một giá trị khác thì các bạn phải làm thế nào? Rất đơn giản, bạn chỉ cần sửa lại command class kia một chút thôi, truyền tham số hoặc option vào cho nó, mỗi lần bạn thay đổi giá trị thì chỉ việc chạy lại command này lại 1 lần. Trong Laravel thì thuộc tính $signature là nơi để định nghĩa arguments và options, như dưới đây:

protected $signature = 'post:update_publish_time {time} {--check}

Arguments được đăng kí một cách dễ dàng với cú pháp {argumentName}, còn option thì là cú pháp {--optionName}. Chúng ta có thể tạo được nhiều arguments và options khác nhau và không cần phải tạo một hàm get arguments hay get options trong class mà chỉ cần gọi nó trong hàm handle() như sau:

/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    // Get single Parameters
    $time = $this->argument('time');
    $check = $this->option('check');

    // Get all
    $arguments = $this->arguments();
    $options = $this->options();
}

Đó là những cú pháp đơn giản nhất để tạo argument và option. Ngoài ra các bạn còn có thêm các cách sử dụng:

  • Argument: posts:update_publish_time {time}.
  • Optional Argument: posts:update_publish_time {time?}.
  • Argument with default value: posts:update_publish_time {time="2020-12-31 00:00:00"}.
  • Boolean Option: posts:update_publish_time --check.
  • Option with Value: posts:update_publish_time --check=.
  • Option with Value and Default: posts:update_publish_time --check=12.

Đăng kí command

Đăng kí command vừa tạo bằng cách thêm tên lớp vào thuộc tính $command trong app/Console/Kernel.php. Khi Artisan khởi động, tất cả các lệnh được liệt kê trong thuộc tính này sẽ được giải quyết bởi các service container và đăng ký với Artisan:

protected $commands = [
    CommandsUpdatePublishTime::class
];

Sau đó các bạn chạy thử lệnh mình tạo và xem trong db đã được update hay chưa nhé:

php artisan posts:update_publish_time

Nếu các bạn khai báo arguments hay options thì có thể truyền thêm vào lệnh trên ví dụ: php artisan posts:update_publish_time "2020-12-31 00:00:00"

Bài viết của mình đến đây là kết thúc. Cảm ơn các bạn đã theo dõi!

Tham khảo

Laravel Document: https://laravel.com/docs/5.5/artisan

0