
Chào mừng các bạn đến với buổi học hôm nay! Tôi là Creyt, và chủ đề nóng hổi chúng ta sẽ "mổ xẻ" ngày hôm nay chính là Route Subdomains trong Laravel. Nghe có vẻ phức tạp, nhưng tin tôi đi, nó chỉ là một cách để chúng ta tổ chức "vương quốc" ứng dụng của mình một cách gọn gàng, khoa học mà thôi.
1. Route Subdomains là gì và tại sao chúng ta cần nó?
Hãy tưởng tượng ứng dụng Laravel của bạn như một tập đoàn đa quốc gia. example.com là trụ sở chính, nơi diễn ra mọi hoạt động kinh doanh cốt lõi. Nhưng tập đoàn này có nhiều phòng ban chuyên biệt, ví dụ như phòng Marketing (marketing.example.com), phòng Quản lý khách hàng (crm.example.com), hay thậm chí là các chi nhánh con dành cho từng đối tác (clientA.example.com).
Route Subdomains chính là cơ chế giúp bạn tạo ra những "phòng ban" hay "chi nhánh" riêng biệt này ngay trong cùng một ứng dụng Laravel. Thay vì phải xây dựng các ứng dụng độc lập rồi kết nối chúng lại, bạn có thể dùng chung một codebase, một cơ sở dữ liệu, nhưng lại phục vụ các tên miền con khác nhau.
Tại sao chúng ta cần nó ư?
- Tổ chức: Giúp phân tách rõ ràng các phần chức năng lớn của ứng dụng. Admin panel thường là một ứng cử viên sáng giá cho subdomain (ví dụ:
admin.yourdomain.com). - Hệ thống đa người thuê (Multi-tenant): Đây là "át chủ bài" của subdomain. Mỗi khách hàng của bạn có thể có một subdomain riêng (ví dụ:
khachhangA.yourdomain.com,khachhangB.yourdomain.com), nhưng tất cả đều chạy trên cùng một mã nguồn và hạ tầng. - Tách biệt chức năng: Giúp đội ngũ phát triển tập trung vào từng phần mà không làm ảnh hưởng đến các phần khác.
- SEO: Đôi khi, các subdomain có thể được coi là các thực thể riêng biệt bởi công cụ tìm kiếm, hữu ích cho chiến lược SEO chuyên biệt.
2. Setup Môi Trường Local (Quan trọng!)
Trước khi "vẽ bản đồ" cho các subdomain, bạn cần đảm bảo môi trường phát triển cục bộ của mình hiểu được chúng. Nếu không, máy tính của bạn sẽ lạc lối giữa "biển" tên miền!
Bước 1: Chỉnh sửa file hosts
Đây là cách bạn "nói" với máy tính của mình rằng các subdomain này trỏ về đâu. Mở file hosts của bạn (thường là C:\Windows\System32\drivers\etc\hosts trên Windows hoặc /etc/hosts trên macOS/Linux) và thêm các dòng sau:
127.0.0.1 yourdomain.test
127.0.0.1 admin.yourdomain.test
127.0.0.1 blog.yourdomain.test
127.0.0.1 *.yourdomain.test # Cho phép mọi subdomain động
Thay yourdomain.test bằng tên miền bạn đang dùng cho dự án Laravel của mình (ví dụ: myapp.test). Dòng cuối cùng với dấu * là để hỗ trợ các subdomain động, rất tiện lợi cho multi-tenant.
Bước 2: Cấu hình Web Server (nếu không dùng Valet/Herd)
Nếu bạn dùng Laravel Valet hoặc Laravel Herd, chúng sẽ tự động xử lý wildcard subdomains cho bạn, cực kỳ tiện lợi! Chỉ cần valet park thư mục dự án là xong. Nếu bạn dùng Apache/Nginx thủ công, bạn cần cấu hình VirtualHost hoặc server block để chấp nhận các subdomain này và trỏ về thư mục public của Laravel.
Ví dụ với Nginx (trong file cấu hình sites-enabled/yourdomain.test):
server {
listen 80;
server_name .yourdomain.test; # Dấu chấm phía trước để bắt mọi subdomain
root /path/to/your/laravel/project/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
3. Cú Pháp "Khai Phá Lãnh Thổ"
Trong Laravel, việc định nghĩa subdomain routes được thực hiện trong file routes/web.php (hoặc routes/api.php nếu bạn muốn API theo subdomain) bằng phương thức Route::domain() hoặc nhóm routes với key domain.
Cú pháp cơ bản:
use Illuminate\Support\Facades\Route;
// Admin Panel
Route::domain('admin.myapp.test')->group(function () {
Route::get('/', function () {
return 'Đây là trang quản trị!';
});
Route::get('/users', function () {
return 'Danh sách người dùng admin.';
});
});
// Main Application (cần đặt sau các subdomain cụ thể để tránh xung đột)
Route::get('/', function () {
return 'Chào mừng đến với ứng dụng chính!';
});
Route::get('/about', function () {
return 'Về chúng tôi.';
});
Khi bạn truy cập admin.myapp.test, bạn sẽ thấy "Đây là trang quản trị!". Còn myapp.test sẽ hiển thị "Chào mừng đến với ứng dụng chính!". Ngon lành cành đào!
Truyền tham số vào Subdomain (Động):
Đây là lúc phép thuật multi-tenant bắt đầu. Bạn có thể bắt một phần của subdomain làm tham số, giống như cách bạn bắt tham số trong URL thông thường.
// User Profiles / Client Portals
Route::domain('{account}.myapp.test')->group(function () {
Route::get('/', function (string $account) {
return 'Chào mừng đến với trang của ' . $account . '!';
});
Route::get('/dashboard', function (string $account) {
return 'Dashboard của ' . $account . '.';
});
});
Bây giờ, nếu bạn truy cập creyt.myapp.test, bạn sẽ thấy "Chào mừng đến với trang của creyt!". Và harvard.myapp.test sẽ là "Chào mừng đến với trang của harvard!". Thật tuyệt vời phải không?
Lưu ý quan trọng: Các route định nghĩa trong Route::domain() sẽ chỉ khớp khi tên miền chính xác khớp với định nghĩa. Các route không có domain() sẽ mặc định khớp với bất kỳ tên miền nào không được định nghĩa cụ thể.

4. Code Ví Dụ Minh Họa (Thực Chiến)
Hãy cùng xây dựng một kịch bản phức tạp hơn một chút với các Controller và Middleware để thấy sức mạnh của nó.
Bước 1: Tạo Controllers
php artisan make:controller AdminController
php artisan make:controller TenantController
Bước 2: Nội dung Controllers
app/Http/Controllers/AdminController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminController extends Controller
{
public function index()
{
return 'Đây là trang chủ quản trị. Xin chào Admin!';
}
public function users()
{
// Logic lấy danh sách người dùng cho admin
$users = ['Alice', 'Bob', 'Charlie'];
return 'Danh sách người dùng: ' . implode(', ', $users);
}
}
app/Http/Controllers/TenantController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TenantController extends Controller
{
public function index(string $account)
{
return 'Xin chào ' . ucfirst($account) . '! Đây là trang chủ riêng của bạn.';
}
public function settings(string $account)
{
// Logic lấy cài đặt cho tenant $account
return 'Cài đặt của ' . ucfirst($account) . '.';
}
}
Bước 3: Định nghĩa Routes trong routes/web.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AdminController;
use App\Http\Controllers\TenantController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Đây là nơi bạn có thể đăng ký các tuyến web cho ứng dụng của mình. Các tuyến này
| được tải bởi RouteServiceProvider trong một nhóm chứa middleware "web". Giờ hãy
| xây dựng một cái gì đó tuyệt vời!
|
*/
// 1. Routes cho Admin Subdomain
Route::domain('admin.myapp.test')->group(function () {
// Có thể thêm middleware 'auth:admin' nếu có hệ thống đăng nhập riêng cho admin
Route::get('/', [AdminController::class, 'index']);
Route::get('/users', [AdminController::class, 'users']);
});
// 2. Routes cho Multi-tenant Subdomain (Động)
Route::domain('{account}.myapp.test')->group(function () {
// Middleware để kiểm tra xem $account có hợp lệ không, ví dụ: AuthTenantMiddleware
Route::get('/', [TenantController::class, 'index']);
Route::get('/settings', [TenantController::class, 'settings']);
});
// 3. Routes cho Main Application (Không có Subdomain)
Route::get('/', function () {
return 'Chào mừng đến với trang chủ ứng dụng chính của chúng ta!';
});
Route::get('/contact', function () {
return 'Liên hệ chúng tôi tại main app.';
});
Với cấu hình này, bạn có thể truy cập:
myapp.test-> Trang chủ ứng dụng chính.admin.myapp.test-> Trang quản trị.creyt.myapp.test-> Trang riêng của Creyt.harvard.myapp.test-> Trang riêng của Harvard.
5. "Mẹo Vặt" Từ Giảng Viên Creyt (Best Practices)
Để sử dụng Route Subdomains một cách "thượng thừa", hãy ghi nhớ vài điều sau:
-
Luôn dùng
Route::group: Nó giúp mã nguồn của bạn gọn gàng, dễ đọc và dễ quản lý. Tránh định nghĩa từng route subdomain riêng lẻ mà không nhóm. Nó giống như việc bạn tổ chức tài liệu vào từng thư mục thay vì vứt bừa bãi trên desktop vậy. -
Cẩn trọng với tham số subdomain: Khi dùng
{account}.myapp.test, hãy luôn có một Middleware hoặc logic kiểm tra xem$accountđó có tồn tại và hợp lệ không. Kẻo người dùng gõabcxyz.myapp.testmà không cóabcxyznào tồn tại, ứng dụng của bạn sẽ "ngơ ngác" ngay. -
Thứ tự định nghĩa quan trọng: Các subdomain cụ thể (ví dụ:
admin.myapp.test) nên được định nghĩa TRƯỚC các subdomain động (ví dụ:{account}.myapp.test). Nếu không,admin.myapp.testcó thể bị bắt bởi{account}.myapp.testvà$accountsẽ nhận giá trị là "admin", gây ra lỗi logic. -
Khi nào nên dùng, khi nào không? Subdomain rất mạnh, nhưng không phải lúc nào cũng là giải pháp tốt nhất. Nếu bạn chỉ cần tách biệt một vài trang con nhỏ,
Route::prefix()hoặcRoute::group(['prefix' => 'admin'])có thể đơn giản và hiệu quả hơn. Chỉ nên dùng subdomain khi bạn thực sự muốn tạo ra một "không gian" riêng biệt về mặt logic hoặc branding. -
Đừng quên file
hostsvà cấu hình server: Đây là "cửa ngõ" để máy tính và server của bạn hiểu được subdomain. Nếu quên bước này, mọi công sức định nghĩa route trong Laravel sẽ "đổ sông đổ biển".
6. Ứng Dụng Thực Tế (Bạn đã thấy ở đâu?)
Subdomain routing không phải là một khái niệm mới mẻ, nó đã được rất nhiều "ông lớn" áp dụng thành công:
- GitHub Pages: Khi bạn tạo một trang web tĩnh trên GitHub, nó thường có dạng
username.github.io. Mỗiusernamelà một subdomain, nhưng tất cả đều được quản lý bởi GitHub. - Shopify: Các cửa hàng trực tuyến được tạo trên Shopify thường có tên miền dạng
mystore.myshopify.com. Mỗimystorelà một subdomain riêng biệt cho từng người bán. - WordPress.com: Tương tự, các blog miễn phí trên WordPress.com thường có dạng
myblog.wordpress.com. - Google App Engine/Heroku: Các nền tảng PaaS này cũng thường cung cấp các subdomain cho ứng dụng triển khai của bạn (ví dụ:
yourapp.appspot.com).
Như bạn thấy, đây không chỉ là lý thuyết suông mà là một công cụ cực kỳ hữu ích trong thế giới lập trình thực tế.
Kết luận
Vậy là chúng ta đã cùng nhau khám phá "nghệ thuật" phân chia lãnh thổ ứng dụng bằng Route Subdomains trong Laravel. Từ việc hiểu khái niệm, cấu hình môi trường, đến viết code thực tế và các mẹo vặt hữu ích. Hy vọng bạn đã nắm vững kiến thức này và sẵn sàng áp dụng nó vào các dự án của mình để tạo ra những ứng dụng Laravel mạnh mẽ, có tổ chức và dễ quản lý hơn. Đừng ngần ngại thực hành và thử nghiệm nhé! Hẹn gặp lại trong buổi học tiếp theo!
Thuộc Series: Lavarel
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!