Closure-Based Commands In Laravel 5.3
Bài đăng này đã không được cập nhật trong 3 năm
Lời mở đầu
Tiếp tục với các chuỗi bài viết về các tính năng mới của laravel 5.3, ngày hôm nay chúng ta sẽ nói về tính năng khác khá thú vị và 1 ví dụ khá hữu ích của nó trong quá trình dev. Đó là :
- Closure-Based Commands
Nào, giờ thì LET GO :
I, Closure-Based Commands
Chắc chắn rằng developer không còn ai lạ gì về các câu command php artisan
cửa laravel rồi, nó là 1 phần đặc biệt và không thể không biết khi đến với laravel ... Mà thôi để đề phòng một số bạn không biết mình xin nói qua luôn :
Artisan
là một CLI được tích hợp trong Laravel, cung cấp một số lệnh(command) hữu dụng trong khi phát triển ứng dụng. Đầu tiên và trước hết muốn sử dụng thì hãy biết ẻm có tồn tại những gì. Để xem tất cả các lệnh của Artisan các bạn gõ lệnh php artisan
trong cmd, kết quả bạn nhận được sẽ là
Như các bạn đã thấy đấy, artisan
cung cấp cho chúng ta nhiều câu lệnh hỗ trỡ cũng như chạy app khi cần thiết như tạo file (migrate, model, controller , ... ), cache các config , vân vân và mây mây =))
Công cụ này rất hay ho, đừng lo vì quá nhiều lệnh bạn chưa nắm được. Cứ đọc trang Help thôi, sẽ có một ngày bạn sẽ gào lên tại sao lại ít lệnh để mình xài như vậy. Oh yeah, Laravel cho phép bạn xây dựng các lệnh riêng của bạn. Bạn có thể truy cập trang tài liệu chính thống của Laravel để xem cách làm .
Trong tài liệu chính thống có nói đến 2 phương pháp làm :
1: Phương pháp chính thống:
- B1: Tạo ra 1 file console trong thư mục
app\console
bằng cách sử dụng commandphp artisan make:command
hoặc copy file command khác ở 1 nơi nào đó ... tùy =)) - B2: Setup file command mới nó sẽ same same như sau :
<?php
namespace App\Console\Commands;
use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;
class SendEmails extends Command
{
protected $signature = 'email:send {user}';
protected $description = 'Send drip e-mails to a user';
protected $drip;
public function __construct(DripEmailer $drip)
{
parent::__construct();
$this->drip = $drip;
}
public function handle()
{
$this->drip->send(User::find($this->argument('user')));
}
}
- B3 : Khai báo comand vào trong
app\console\Kenel.php
Đái khái thế, trong bài viết này mình sẽ không nói rõ chi tiết phương pháp này vì nó cũng đk sử dụng nhiều rồi nên mình xin phép bỏ qua ...
2, Closure-Based Commands
Như các bạn đã thấy , với phương pháp chính thống, việc tạo ra 1 cấu command khá lằng nhằng và viết thêm nhiều file các kiểu .... Việc phải tạo hẳn 1 câu class cho 1 câu command đơn giản làm mình cảm thấy hết sức mệt mỏi ... Có cách nào đơn giản hơn không và thật may là với version 5.3 này chúng ta đã có.
Ok, các bạn có để ý thấy rằng trong laravel 5.3 có tách riếng thư mục router ra , ok cũng chả có gì đặc biệt chỉ là tách router ra thành 2 file web.php
và api.php
theo từng mục đích sử dụng thôi ... Ớ thế cái thư mục console.php
kia thì để làm gì ? ? ? ? ? ?
<?php
use Illuminate\Foundation\Inspiring;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->describe('Display an inspiring quote');
Bên trên là nội dung mặc định của nó sau, sau 1 hồi vọc trên document của laravel thì cuối cùng mình cũng biết nó là cái gì . Đây là Closure-Based Commands
việt sub thì mình chịu luôn hiểu ngắn gọn rằng là file này cung cấp cho bạn khả năng định nghĩa command như một class command thông thường trong, nó giông giống kiểu bạn định nghĩa router trong HTTP request đó chẳng qua đây là command thôi.
Giờ đặt ra 1 câu hỏi, thế giờ tôi ko thích viết định nghĩa command này trong file console.php
mà viết ở file khác được không . Câu trả lời là được, đơn giản bạn chỉ cần vào file app/Console/Kerner.php
hàm commands
điều chỉnh là được :
protected function commands()
{
require base_path('routes/console.php');
}
Hàm này có trách nhiệm load các command từ các file router vào để chạy và việc cảu bạn đơn giản chỉ là import thêm file hoặc update file vào là đk
Để làm rõ hơn về cách sử dụng cũng như chức năng của phương pháp này, mình sẽ hướng dẫn các bạn làm 1 câu command khá thú vị :
Trong quá trình develop, laravel có cung cấp các câu lệnh tạo model, migrate ,..,.. ok, mình thấy sử dụng khá là ngon lành và chả có vấn đề gì cả nhưng vấn đề là trong project của mình để lấy dữ liệu thì không chỉ cần có controler model và view mà cần thêm cả repository, serivice nữa ... Mà mình lại không thể dùng lệnh để tạo ra chúng, làm sao bây giờ , chả có nhẽ mỗi lần tạo lại copy paste hay viết lại à và vì thế nên mình quyết định viết 1 câu comand để gennerate ra các file mà mình muốn.
Ok, bắt tay vào làm nào :
- Đầu tiên, trong
console.php
mình khai báo thêm 1 command nữa như sau :
Artisan::command('make:file', function () {
//body command
})
- Như vậy là chúng ta đã khai báo được 1 câu command là
php artisan make:file
tuy nhiên làm như vậy câu command của chúng ta không có description trong list command, Vậy nếu muốn có des bạn cần thêm vào như sau :
Artisan::command('make:file', function () {
//body command
})->describe('Generate a class');
- Bước 2, mình cần chuyền 1 biến
type
gì đó để xác định được xem mình muốn tạo file gì repository hay service vàname
của file cần tạo.. Mình cần làm như sau :
Artisan::command('make:file {type} {name}', function () {
//body command
})->describe('Generate a class');
- Và nếu cần viết description cho biến này thì mình sẽ viết như sau
Artisan::command('make:file {type : The type of file you want generate} {name : name of file}', function () {
//body command
})->describe('Generate a class');
- Bước 3: Tạo file template cho repository hay service .. Tạo mới 1 thư mục
template
trong app và add fileservice.txt
có nội dung như sau vào :
<?php
namespace App\Repositories;
use App\Repositories\EloquentRepository;
class {name}Repository extends EloquentRepository
{
public function model()
{
return \App\Models\{name}::class;
}
}
- Bước 4 : Xử lý hàm trong command như sau :
Artisan::command('make:file {type : The type of file you want generate} {name : Name of file}', function () {
$fileName = $this->argument('name');
$templateName = 'service.txt';
$saveForder = 'Service';
if ($this->argument('type') == 'repository') {
$templateName = 'repository.txt';
$saveForder = 'Repository';
}
$template = File::get('app/template/' . $templateName);
$compiled = str_replace('{name}', $fileName, $template);
File::put("app/{$saveForder}/{$fileName}.php", $compiled);
})->describe('Generate a class');
- Bước 5: Cuối cùng chúng ta có thể tạo 1 Repository vs câu lệnh như sau
php artisan make:file repository Address
OK, đến đây mình cũng xin kết thúc bài viết ở đây, hy vọng bài viết hữu ích cho bạn !
TÀI LIỆU THAM KHẢO
All rights reserved