Laravel: Console Command
Hôm nay mình xin giới thiệu với các bạn về Console Command trong Laravel. Introduction 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ó ...
Hôm nay mình xin giới thiệu với các bạn về Console Command trong Laravel.
Introduction
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
Writing Commands
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
Để 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 signature và description 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 AppConsoleCommands; use AppUser; use AppDripEmailer; use IlluminateConsoleCommand; 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 AppUser; use AppDripEmailer;
Artisan::command('email:send {user}', function (DripEmailer drip,drip, drip,user) { drip−>send(User::find(drip->send(User::find(drip−>send(User::find(user)); });
<br> *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 {$$roject}!"); })->describe('Build the project');
<br> ### **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. <br> ***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 $$ignature = '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}
<br> ***Options*** 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 $$ignature = '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
<br> *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 $$ignature = '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 đủ:
email:send {user} {--Q|queue}
<br> ***Input Arrays*** 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
<br> ***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 $$ignature = 'email:send {user : The ID of the user} {--queue= : Whether the job should be queued}';