[Laravel 7] Tổ chức theo dạng Package/Module trong ứng dụng Laravel - P1: Giới thiệu và khởi tạo cấu trúc thư mục cơ bản

Đăng bởi:

Nguyễn Viết Hiếu

Đăng ngày:

Jan 25, 2021

Đăng ở:

Xây dựng Website

Lập trình viên như chúng ta thường hướng đến việc code một nơi và có thể dùng ở nhiều nơi khác hay còn gọi là tái sử dụng code. Vậy các bạn đã từng nghĩ đến việc tái sử dụng các tính năng, việc tái sử dụng tính năng biểu hiện ở chỗ, một hay một nhóm tính năng có thể tái sử dụng ở nhiều dự án khác nhau thay vì là một dự án duy nhất.

Trong Laravel, để lập trình tính năng, theo cách truyền thống đó là thay đổi trực tiếp tại các thự mục /app, /config, ... và rất nhiều công ty cũng sử dụng theo cách này, nó không sai và còn được laravel khuyến khích sử dụng. Tuy nhiên, Laravel lại là một framework thay đổi chóng mặt và cách code như trên khiến cho ứng dụng của chúng ta quá ràng buộc vào Laravel từ đó rất khó khi upgrate lên các phiên bản Laravel cao hơn.

Để giải quyết vấn đề tái sử dụng và giúp các tính năng của chúng ta có thể sử dụng cho các phiên bản Laravel trong tương lai thì chúng ta cần phải phát triển theo dạng Package/Module.

Giới thiệu

Package là là một dạng đóng gói tính năng để thêm vào trong các dự án. Package có thể là bất cứ thứ gì từ việc xử lý ngày giờ như Carbon hay nguyên bộ framework như Laravel. Có rất nhiều loại Package, một số Package thì stand-alone, nghĩa là chúng có thể hoạt động với bất kỳ framework nào miễn là sử dụng chung 1 loại ngôn ngữ (Carbon là một ví dụ), một số Package khác thì lại được tạo ra để sử dụng cho 1 framework nhất định.

Bài hướng dẫn này phần lớn sẽ nói về việc phát triển các Package dành cho Laravel và phiên bản mình sử dụng để Hướng dẫn đó là Laravel 7 (Các phiên bản Laravel khác cũng có thể áp dụng). Và ở bài đầu tiên này mình sẽ đưa ra cấu trúc thư mục và khai báo ban đầu cho một Package.

Khởi tạo Package

1. Cấu trúc thư mục Package cơ bản

Một Package cơ bản sẽ gồm có cấu trúc thư mục như sau:

packages
├── demo
│   ├── configs
│   │   └── demo.php
│   ├── helpers
│   │   └── functions.php
│   ├── migrations
│   ├── resources
│   │   └── assets
│   │   └── lang
│   │   └── views
│   ├── routes
│   │   └── routes.php
│   ├── src
│   │   └── Commands
│   │   └── Http
│   │   |   └── Controllers
│   │   |   └── Middlewares
│   │   └── Models
│   │   └── Providers
│   │   |   └── DemoServiceProvider.php
│   ├── composer.json
│   ├── Readme.md
├── demo2
│   ├── ...

Các thư mục tại Package có công dụng giống như các thư mục cùng tên tại thư mục chính. Thư mục "src" có công dụng như thư mục "\app". Tên các thư mục không nhất thiết phải đặt giống mình nhưng mình khuyến khích các bạn chỉ thay đổi khi đã hiểu rõ về hướng phát triển Package.

P/S: Các thư mục trên không nhất thiết bắt buộc phải có mà nó còn tùy theo Package đó có dùng hay không.

2. Khai báo Package

2.1: Khai báo composer.json tại packages

Đây là thư mục quan trọng nhất của một Package. Nó giúp khai báo Package với "composer" từ đó khởi tạo đường dẫn dạng link đến thư mục "\vendor".

Cấu trúc file cơ bản được viết như sau:

{
    // Tên của package dùng để khai báo tại composer.json tại root
    "name": "packages/demo", 
    // Đây là phần mô tả tính năng của Package
    "description": "Mô tả", 
    //
    "type": "library",
    "license": "MIT",
    "minimum-stability": "dev",
    // Khai báo tác giả
    "authors": [
        {
            "name": "Tac gia",
            "email": "tac_gia@gmail.com"
        }
    ],
    // Khai báo các packages khác
    "require": {
        //
    },
    // Khai báo namespace psr-4
    "autoload": {
        "psr-4": {
            "Package\\Demo\\": "src/"
        }
    },
    "extra": {
        "laravel": {
            // Khai báo ServiceProvider của Package
            "providers": [
                "Package\\Demo\\Providers\\DemoServiceProvider"
            ],
            "aliases": {}
        }
    }
}

P/S: Mình đã giải thích các khai báo tại ghi chú và các ghi chú này cần xóa đi khi chạy để tránh gây lỗi.

2.2 Khởi tạo ServiceProvider của Package

ServiceProvider là điểm kết nối giữa package của bạn và Laravel. Một ServiceProvider chịu trách nhiệm kết nối các thành phần vào trong container của Laravel và thông báo cho Laravel vị trí để load các tài nguyên của package như views, config, helpers,...Một ServiceProvider kế thừa từ class "Illuminate\Support\ServiceProvider" và chứa hai phương thức chính là register và boot.

Một ServiceProvider cơ bản có cấu trúc như sau:

<?php

    namespace Package\Demo\Providers;
    
    use Illuminate\Support\Facades\File;
    use Illuminate\Support\Facades\Log;
    use Illuminate\Support\ServiceProvider;
    use Illuminate\Support\Facades\Schema;

    class DemoServiceProvider extends ServiceProvider
    {

        /**
        * Register bindings in the container.
        */
        public function register()
        {
            //
        }

        public function boot()
        {
            //
        }

    }

2.3 Khai báo package tại composer.json tại thư mục gốc

Chúng ta sẽ khai báo "name" của Package tại "require" và khai báo thư mục chứa Package tại "repositories".

{
    ...
    "require": {
        ...
        "package/demo": "dev-master"
    },
    ...
    "repositories": [
        {
            "type": "path",
            "url": "./packages/*"
        }
    ]
}

2.4 Kiểm thử Package

B1: Khởi chạy "composer update" để composer nạp "package/demo" vào vendor (Chỉ cần chạy 1 lần khi khai báo package, sau khi khai báo thì mỗi thay đổi tại package sẽ tự động được update vào thư mục tại vendor)

B2: Cập nhật lại ServiceProvider để kiểm tra xem package đã được update thành công hay chưa:

...
public function boot()
{
    dd('Kiểm tra Package');
}
...

B3: Refresh (F5) lại trang nếu hiện ra đòng chữ "Kiểm tra Package" thì nghĩa là Package của bạn đã được chạy thành công.

Tổng kết

Tổ chức theo dạng Package/Module là một dạng phát triển khá hay giúp chúng ta có thể sử dụng được những Module được dựng sẵn mà mất rất ít công sức, dễ dàng duy trì và phát triển, đặc biệt PHỤ THUỘC ÍT VÀO LARAVEL cũng như dễ dàng CẬP NHẬT ĐƯỢC PHIÊN BẢN nếu như laravel lên bản 8 hay 9.

Đây là bài đầu tiên của series "Tổ chức theo dạng Package/Module trong ứng dụng Laravel", các bài viết tiếp theo mình sẽ tiếp tục hướng dẫn khai báo các thành phần quan trọng khác của một Package và hi vọng nó có thể giúp ích được cho mọi người.

Nguyễn Viết Hiếu

Bình luận

Để lại bình luận

Email và số điện thoại sẽ không được công khai. Những trường bắt buộc được đánh dấu *

Repository deleted Your repository has remove
Loading