Nội dung bài viết
- 1.Cây thư mục Laravel mặc định
- 2.Vai trò của các thư mục gốc
- 2.1app
- 2.2bootstrap
- 2.3config
- 2.4database
- 2.5public
- 2.6resources
- 2.7routes
- 2.8storage
- 2.9tests
- 2.10vendor
- 3.Các thư mục con trong app được tạo khi nào?
- 4.Thay đổi so với Laravel 10 trở về trước
- 5.Tổ chức dự án Laravel theo module
- 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.

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ục | Tạo bởi lệnh | Chứa gì |
|---|---|---|
| app/Http/Middleware | make:middleware | Middleware tự viết |
| app/Console/Commands | make:command | Lệnh Artisan tự viết |
| app/Events, app/Listeners | make:event, make:listener | Sự kiện và bộ xử lý sự kiện |
| app/Jobs | make:job | Tác vụ đưa vào hàng đợi |
| app/Mail, app/Notifications | make:mail, make:notification | Email và thông báo |
| app/Policies | make:policy | Phân quyền theo model |
| app/Rules | make:rule | Quy 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.phpvà thuộc tính$routeMiddleware: bỏ từ Laravel 11; middleware toàn cục, nhóm và alias khai báo trongbootstrap/app.php.app/Console/Kernel.php: bỏ; lịch chạy tác vụ viết trongroutes/console.phpbằng facadeSchedule.app/Exceptions/Handler.php: bỏ; xử lý exception trongbootstrap/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.
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