X

Laravel: Console Command trong laravel phần 1

Chắc hẳn các bạn đã và đang thiết kế web bằng Laravel, hay đang học về laravel đều đã dùng qua Command Artisan của laravel rồi, nhưng các bạn đã hiểu hết chưa? Hôm nay mình xin giới thiệu với các bạn về Console Command trong laravel.

Giới thiệu về Console Command trong laravel

Artisan là giao diện command-line được thêm vào Laravel. Nó cung cấp một số lệnh hữu ích mà có thể hỗ trợ bạn trong khi xây dựng ứng dụng của mình. Để xem danh sách tất cả các lệnh Artisan có sẵn, bạn có thể sử dụng lệnh list.

php artisan list

Mỗi lệnh cũng bao gồm một màn hình trợ giúp để mô tả đối số và các tùy chọn có sẵn của lệnh. Để xem một màn hình trợ giúp, chỉ cần thêm help đứng trước command mà bạn muốn tìm hiểu:

php artisan help migrate

Viết Commands cho Laravel

Ngoài các command được cung cấp bởi Artisan, bạn cũng có thể xây dựng các command tùy chỉnh của riêng mình. Các command thường được lưu trữ trong app/Console/Commands. Tuy nhiên, bạn có thể tự do lựa chọn vị trí lưu trữ của riêng bạn, miễn là các command của bạn có thể được nạp bởi Composer.

Generating Commands trong laravel

Để tạo ra một command mới, sử dụng lệnh của Artisan make:command. Lệnh này sẽ tạo ra một command class trong app/Console/Commands. Đừng lo lắng nếu thư mục này không tồn tại trong ứng dụng của bạn, vì nó sẽ được tạo ra khi lần đầu tiên bạn chạy câu lệnh Artisan make:comand. Các command này được tạo ra sẽ bao gồm các thiết lập mặc định của properties và methods có mặt trên tất cả các command.

php artisan make:command SendEmails

Tiếp theo, bạn sẽ cần phải đăng ký các command này trước khi nó có thể được thực hiên thông qua Artisan CLI.

Command Structure

Sau khi generate lệnh của bạn, bạn nên fill vào các thuộc tính signaturedescription của class, mà sẽ được sử dụng khi hiển thị các command của bạn trên màn hình list. Các phương thức handle sẽ được gọi khi câu command của bạn được thực thi. Bạn có thể đặt logic của bạn trong phương thức này.

Chúng ta hãy xem xét một ví dụ. Lưu ý rằng chúng ta có thể inject bất kỳ dependencies nào chúng ta cần đến constructor của lệnh.

<?php

namespace App\Console\Commands;

use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;

class SendEmails extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'email:send {user}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send drip e-mails to a user';

    /**
     * The drip e-mail service.
     *
     * @var DripEmailer
     */
    protected $drip;

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

        $this->drip = $drip;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->drip->send(User::find($this->argument('user')));
    }
}

Closure Commands

Closure based commands cung cấp một thay thế cho việc xác định console commands giống như class. Nó giống như việc là route Closure là một thay thế cho controllers. Hãy hình dung command Closure giống như một thay thế cho các command class. Cùng với phương thức commands của file app/Console/Kernel.php của bạn, Laravel cũng load file routes/console.php.

/**
 * Register the Closure based commands for the application.
 *
 * @return void
 */
protected function commands()
{
    require base_path('routes/console.php');
}

Mặc dù file này không định nghĩa các HTTP route, nó định nghĩa các console dựa trên entry points (routes) vào ứng dụng của bạn. Trong file này, bạn có thể định nghĩa tất cả các Closure dựa trên routes sử dụng phương thức Artisan::command. Phương thức command chấp nhận 2 đối số: command signature và 1 Closure tiếp nhận các commands argument và options:

Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
});

Type-Hinting Dependencies

Ngoài việc tiếp nhận arguments và options của command, các command Closure cũng có thể type-hint thêm dependencies mà bạn muốn giải quyết ra khỏi service container

use App\User;
use App\DripEmailer;

Artisan::command('email:send {user}', function (DripEmailer $drip, $user) {
    $drip->send(User::find($user));
});

 

Closure Command Descriptions

Khi định nghĩa 1 Closure based command, bạn có thể sử dụng phương thức describe để thêm 1 description cho command. Description này sẽ được hiển thị khi bạn chạy lệnh php artisan list hoặc php artisan help:

Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
})->describe('Build the project');

Defining Input Expectations

Khi viết console command, nó là phổ biến để thu thập thông tin từ người sử dụng thông qua các argument hoặc option. Laravel làm cho nó trở nên thuận tiện để xác định các đầu vào mà bạn mong đợi từ người dùng bằng cách sử dụng signature property trên command của bạn. signature property cho phép bạn xác định name, arguments và option cho các lệnh trong single, expressive, route-like syntax.

Arguments

Tất cả user đã thêm vào các argument và option được bọc trong dấu ngoặc nhọn {}. Trong ví dụ sau, command định nghĩa một đối số bắt buộc: user:

/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user}';

Bạn cũng có thể tạo ra các đối số tùy chọn và định nghĩa các giá trị mặc định cho các đối số:

// Optional argument...
email:send {user?}

// Optional argument with default value...
email:send {user=foo}

Options trong command của Laravel

Options, giống như argument, là một dạng khác của user input. Option được bắt đầu bằng 2 dấu gạch nối (--) khi mà chúng được định nghĩa trên dòng lênh. Có 2 loại options: nhận giá trị và không nhận giá trị. Option không nhận một giá trị serve giống như 1 boolean "switch". Chúng ta hãy xem ví dụ:

/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue}';

Trong ví dụ này, --queue switch có thể được chỉ định khi gọi lệnh Artisan. Nếu --queue swtich được thông qua, giá trị của các option sẽ là true. Nếu không, các giá trị sẽ là false.

php artisan email:send 1 --queue

 

Options With Values

Tiếp theo, chúng ta hãy nhìn vào 1 option yêu cầu 1 giá trị. Nếu người dùng phải chỉ định 1 giá trị cho option đó, hậu tố tên option với 1 dấu =:

/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue=}';

Trong ví dụ này, người dùng có thể vượt qua 1 giá trị cho các option như sau:

php artisan email:send 1 --queue=default

Bạn có thể gán giá trị mặc định cho option bằng cách định nghĩa các giá trị mặc định sau tên option. Nếu không có giá trị option được đưa vào bởi người sử dụng, giá trị mặc định sẽ được sử dụng:

email:send {user} {--queue=default}

Option Shortcuts

Để gán 1 shortcut khi xác định 1 option, bạn có thể định rõ nó trước tên option và sử dụng 1 dấu | để tách các shortcut tf tên option đầy đủ:

Input Arrays - nhập giá trị dạng Array cho command laravel

Nếu bạn muốn xác định đối số hoặc option truyền vào là array, bạn có thể sử dụng ký tự *. Đầu tiên, chúng ta hãy xem 1 ví dụ:

email:send {user*}

Khi gọi phương thức này, các đối số user có thể đượng thông qua trong order đến các dòng lệnh. Ví dụ, command sau sẽ thiết lập giá trị của user đến ['foo', 'bar']

php artisan email:send foo bar

Khi xác định 1 option mà mong đợi 1 đầu vào là array, mỗi giá trị của option vượt qua dòng lệnh nên được bắt đầu với tên option :

email:send {user} {--id=*}

php artisan email:send --id=1 --id=2

Input Descriptions

Bạn có thể gán description đến đối số đầu vào và các option bằng cách tách các tham số từ description sử dụng dấu 2 chấm :. Nếu bạn cần thêm không gian để định nghĩa command của bạn, bạn có thể định nghĩa nó trên nhiều dòng:

/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send
                        {user : The ID of the user}
                        {--queue= : Whether the job should be queued}';