Bỏ qua đến nội dung chính

Cấu trúc thư mục Laravel và cách tổ chức theo module

Giải thích cây thư mục mặc định của Laravel bản hiện hành, vai trò từng thư mục, những gì thay đổi từ Laravel 11 và cách tổ chức dự án lớn theo module.

Tan Hien
Founder
Cập nhật 6 phút đọc
Chia sẻ:
Cấu trúc thư mục Laravel và cách tổ chức theo module
Nội dung bài viết
  1. 1.Cây thư mục Laravel mặc định
  2. 2.Vai trò của các thư mục gốc
  3. 2.1app
  4. 2.2bootstrap
  5. 2.3config
  6. 2.4database
  7. 2.5public
  8. 2.6resources
  9. 2.7routes
  10. 2.8storage
  11. 2.9tests
  12. 2.10vendor
  13. 3.Các thư mục con trong app được tạo khi nào?
  14. 4.Thay đổi so với Laravel 10 trở về trước
  15. 5.Tổ chức dự án Laravel theo module
  16. 5.1Kinh nghiệm từ Hozitech

Một dự án Laravel 13 mới gồm 10 thư mục gốc: app (code chính), bootstrap (khởi động và cấu hình ứng dụng), config, database, public (điểm vào index.php), resources (view, CSS, JS), routes, storage, tests và vendor. Từ Laravel 11, khung ứng dụng gọn hơn: không còn app/Http/Kernel.php, middleware cấu hình trong bootstrap/app.php.

Bài viết mô tả cây thư mục mặc định, vai trò từng thư mục, những gì đã thay đổi so với các bản cũ và cách tổ chức dự án lớn theo module.

Bảng tóm tắt cấu trúc thư mục Laravel: app, bootstrap, config, database, public, resources, routes, storage, tests, vendor
Vai trò của 10 thư mục gốc trong dự án Laravel mặc định.

Cây thư mục Laravel mặc định

Đây là cấu trúc sau khi chạy laravel new example-app (không chọn starter kit), theo tài liệu Directory Structure của Laravel 13 (truy cập 01/10/2026). Thư mục node_modules và một số file cấu hình nhỏ được lược bớt.

example-app/
├── app/
│   ├── Http/
│   │   └── Controllers/
│   │       └── Controller.php
│   ├── Models/
│   │   └── User.php
│   └── Providers/
│       └── AppServiceProvider.php
├── bootstrap/
│   ├── app.php
│   ├── providers.php
│   └── cache/
├── config/
├── database/
│   ├── factories/
│   ├── migrations/
│   ├── seeders/
│   └── database.sqlite
├── public/
│   └── index.php
├── resources/
│   ├── css/
│   ├── js/
│   └── views/
├── routes/
│   ├── console.php
│   └── web.php
├── storage/
│   ├── app/
│   ├── framework/
│   └── logs/
├── tests/
│   ├── Feature/
│   └── Unit/
├── vendor/
├── .env
├── artisan
├── composer.json
├── package.json
└── vite.config.js

Vai trò của các thư mục gốc

app

Chứa gần như toàn bộ class của ứng dụng, namespace App, nạp tự động theo chuẩn PSR-4. Mặc định chỉ có Http, Models và Providers; các thư mục khác được tạo khi bạn chạy lệnh make tương ứng (xem phần sau).

bootstrap

File app.php khởi tạo ứng dụng và là nơi cấu hình routing, middleware, xử lý exception. File providers.php liệt kê service provider của ứng dụng. Thư mục cache chứa file cache do framework sinh ra (route, service…) để tăng tốc.

config

Các file cấu hình: app.php, database.php, mail.php… Giá trị thay đổi theo môi trường (mật khẩu, khóa API) nên đặt trong .env rồi đọc qua env() trong file config, không ghi cứng.

database

Migration (định nghĩa bảng), factory (dữ liệu giả cho test), seeder (dữ liệu mẫu) và file database.sqlite khi dùng SQLite mặc định.

public

Chứa index.php, điểm vào của mọi request, cùng ảnh, CSS, JS đã build. Tên miền phải trỏ document root vào thư mục này, không trỏ vào thư mục gốc dự án.

resources

View Blade (resources/views) và mã CSS, JS chưa biên dịch. Lưu ý: view nằm ở đây, không nằm trong app.

routes

Mặc định có web.php (route dùng nhóm middleware web: session, chống CSRF, mã hóa cookie) và console.php (lệnh Artisan dạng closure, lập lịch tác vụ). Muốn có api.php hoặc channels.php, chạy php artisan install:api hoặc php artisan install:broadcasting. Xem thêm cách khai báo route trong Laravel.

storage

Gồm app (file ứng dụng sinh ra), framework (cache, session dạng file, view đã biên dịch) và logs. File người dùng tải lên cần truy cập công khai đặt ở storage/app/public, rồi tạo liên kết bằng php artisan storage:link.

tests

Test mẫu cho Pest hoặc PHPUnit, chia Feature và Unit. Chạy bằng php artisan test.

vendor

Thư viện do Composer cài. Không sửa trực tiếp file trong đây và không đưa thư mục này lên Git.

Các thư mục con trong app được tạo khi nào?

Thư mụcTạo bởi lệnhChứa gì
app/Http/Middlewaremake:middlewareMiddleware tự viết
app/Console/Commandsmake:commandLệnh Artisan tự viết
app/Events, app/Listenersmake:event, make:listenerSự kiện và bộ xử lý sự kiện
app/Jobsmake:jobTác vụ đưa vào hàng đợi
app/Mail, app/Notificationsmake:mail, make:notificationEmail và thông báo
app/Policiesmake:policyPhân quyền theo model
app/Rulesmake:ruleQuy tắc validation tự viết

Xem toàn bộ lệnh sinh code bằng php artisan list make.

Thay đổi so với Laravel 10 trở về trước

Nếu bạn đọc tài liệu hoặc dự án cũ, sẽ gặp các file không còn trong khung ứng dụng mới:

  • app/Http/Kernel.php và thuộc tính $routeMiddleware: bỏ từ Laravel 11; middleware toàn cục, nhóm và alias khai báo trong bootstrap/app.php.
  • app/Console/Kernel.php: bỏ; lịch chạy tác vụ viết trong routes/console.php bằng facade Schedule.
  • app/Exceptions/Handler.php: bỏ; xử lý exception trong bootstrap/app.php.
  • Năm service provider mặc định gom lại còn AppServiceProvider.
  • routes/api.php, routes/channels.php: không có sẵn, cài khi cần.

Ví dụ đăng ký alias middleware ở Laravel 13 (thay cho $routeMiddleware trong Kernel cũ):

// bootstrap/app.php
use App\Http\Middleware\EnsureUserIsSubscribed;

->withMiddleware(function (Middleware $middleware): void {
    $middleware->alias([
        'subscribed' => EnsureUserIsSubscribed::class,
    ]);
})

Dự án nâng cấp từ bản cũ không bắt buộc chuyển sang cấu trúc mới; cấu trúc gọn chỉ áp dụng mặc định cho dự án tạo mới. Chi tiết luồng chạy qua bootstrap/app.php có trong bài vòng đời request của Laravel; cách viết middleware xem bài middleware trong Laravel.

Tổ chức dự án Laravel theo module

Với dự án nhỏ, cấu trúc mặc định là đủ. Khi dự án có nhiều phân hệ (blog, sản phẩm, đơn hàng, thanh toán…), thư mục app/Http/Controllers và app/Models sẽ dài hàng trăm file. Lúc đó có thể chia theo module: mỗi module là một "Laravel thu nhỏ" có controller, model, route, view, migration riêng.

Gói phổ biến cho cách làm này là nwidart/laravel-modules (lưu ý tên gói có chữ "s"). Phiên bản gói đi theo phiên bản Laravel: Laravel 13 dùng ^13.0. Cài đặt và tạo module:

composer require nwidart/laravel-modules
php artisan module:make Blog

Module mới nằm trong thư mục Modules/Blog. Cấu trúc rút gọn theo tài liệu của gói (bản 13):

Modules/
└── Blog/
    ├── app/
    │   ├── Http/Controllers/
    │   ├── Models/
    │   └── Providers/
    ├── database/
    │   ├── migrations/
    │   └── seeders/
    ├── resources/views/
    ├── routes/
    │   └── web.php
    └── composer.json

Một số bước cấu hình (autoload trong composer.json, bật/tắt module) thay đổi theo phiên bản gói, nên làm theo đúng tài liệu tại laravelmodules.com.

Kinh nghiệm từ Hozitech

Tác giả thường không giữ cấu trúc mặc định cho dự án lớn mà chia theo module để tái sử dụng giữa các dự án. Mã nguồn website Hozitech cũng được chia thành các module như blog, trang, media, SEO, menu, liên hệ; mỗi module có route, migration, view riêng nên có thể bật, tắt hoặc mang sang dự án khác mà không kéo theo phần còn lại. Đổi lại, cần quy ước đặt tên và ranh giới giữa các module ngay từ đầu, nếu không các module sẽ gọi chéo lẫn nhau và mất lợi ích tách biệt. Người mới nên nắm chắc tổng quan Laravel và cấu trúc mặc định trước khi chuyển sang module.

Tan Hien

Về tác giả

Founder

Xin chào mình là Hiền hiện đang là Founder của Hozitech. Mình là kỹ sư phần mềm có hơn 9+ năm kinh nghiệm trong lĩnh vực thiết kế website, ứng dụng di động... Gần đây mình đang nghiên cứu thêm về lĩnh vực marketing. Mình rất vui khi được chia sẽ những kiến thức và kinh nghiệm của mình đến mọi người!

Câu hỏi thường gặp

Câu hỏi thường gặp

Sẵn sàng bắt đầu dự án của bạn?

Hãy để chúng tôi giúp bạn biến ý tưởng thành hiện thực. Đăng ký tư vấn miễn phí ngay hôm nay để nhận được giải pháp công nghệ tối ưu cho doanh nghiệp.