0

Closure-Based Commands In Laravel 5.3

ME6tgVZNTAmfdTb5H0GG_laravel-5-3-new-features-updates.png

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à

artisan.png

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 command php 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.phpapi.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 file service.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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí