Lifecycle & Service Provider
1. Vòng đời Laravel (Laravel Lifecycle)¶
Khái niệm cơ bản¶
Vòng đời Laravel là quá trình từ khi nhận request đến khi trả về response. Hiểu đơn giản như "hành trình" của một yêu cầu từ người dùng.
Các bước chi tiết trong vòng đời:¶
Bước 1: Entry Point (Điểm vào)
- Mọi request đều bắt đầu từ file public/index.php
- File này load Composer autoloader và khởi tạo Laravel application
Bước 2: HTTP/Console Kernels - Request được gửi đến HTTP Kernel hoặc Console Kernel - HTTP Kernel xử lý web requests, Console Kernel xử lý Artisan commands
Bước 3: Service Providers - Tất cả Service Providers được đăng ký và boot - Đây là nơi các services được binding vào container
Bước 4: Routing - Request được so khớp với routes đã định nghĩa - Middleware được thực thi (before request)
Bước 5: Controller/Action - Controller method được gọi - Business logic được xử lý
Bước 6: Response - Kết quả được trả về dưới dạng Response - Middleware được thực thi (after request)
Bước 7: Terminate - Cleanup và các tác vụ sau khi response được gửi
2. Service Container¶
Định nghĩa¶
Service Container là "chiếc hộp" chứa tất cả các services/dependencies của ứng dụng. Nó như một "kho chứa thông minh" biết cách tạo và quản lý objects.
Chức năng chính:¶
- Dependency Injection: Tự động inject dependencies vào class
- Binding: Đăng ký cách tạo objects
- Resolution: Tạo và trả về objects khi cần
Ví dụ thực tế:¶
// Binding vào container
app()->bind('PaymentService', function() {
return new PaymentService(new BankGateway());
});
// Resolve từ container
$paymentService = app('PaymentService');
3. Service Provider¶
Định nghĩa¶
Service Provider là nơi đăng ký và cấu hình các services vào Container. Giống như "người quản lý kho" - quyết định có gì trong kho và cách lấy ra.
Hai phương thức chính:¶
register(): Đăng ký services vào container
public function register()
{
$this->app->bind('MyService', MyService::class);
}
boot(): Thực hiện các tác vụ sau khi tất cả services đã được đăng ký
public function boot()
{
// Cấu hình routes, views, etc.
}
4. Các trường hợp load Service Provider¶
A. Load từ đầu và tắt (Eager Loading)¶
Khi nào xảy ra:
- Service Provider được khai báo trong config/app.php mà KHÔNG có thuộc tính $defer = true
- Các core providers như RouteServiceProvider, ViewServiceProvider
Vòng đời:
Khởi tạo App → Load tất cả Eager Providers → register() → boot() → Xử lý request → Terminate
Ví dụ:
// AppServiceProvider - luôn load khi khởi động
class AppServiceProvider extends ServiceProvider
{
// Không có $defer = true
public function register() {
// Đăng ký services ngay khi app khởi động
}
}
B. Load và chạy mãi (Singleton Services)¶
Khi nào xảy ra: - Services được bind dưới dạng singleton - Services cần duy trì state trong suốt request lifecycle
Cách hoạt động:
// Bind singleton - chỉ tạo 1 instance duy nhất
$this->app->singleton('CacheManager', function() {
return new CacheManager();
});
// Mỗi lần resolve đều trả về cùng 1 instance
$cache1 = app('CacheManager'); // Tạo mới
$cache2 = app('CacheManager'); // Trả về instance cũ
// $cache1 === $cache2 (true)
C. Load khi cần - Deferred Providers (Lazy Loading)¶
Khi nào xảy ra:
- Service Provider có $defer = true
- Chỉ load khi service thực sự được sử dụng
Ví dụ:
class MailServiceProvider extends ServiceProvider
{
protected $defer = true; // Đánh dấu là deferred
protected $provides = ['mailer']; // Khai báo services cung cấp
public function register()
{
$this->app->singleton('mailer', function() {
return new MailManager();
});
}
public function provides()
{
return $this->provides;
}
}
Vòng đời Deferred Provider:
App khởi động → Skip deferred providers →
Request cần 'mailer' → Load MailServiceProvider → register() → boot() →
Sử dụng service → End request
5. So sánh các loại Service Provider¶
| Loại | Khi load | Ưu điểm | Nhược điểm | Ví dụ |
|---|---|---|---|---|
| Eager | Ngay khi app khởi động | Sẵn sàng ngay, nhanh khi sử dụng | Tốn memory, chậm boot time | RouteServiceProvider |
| Deferred | Khi cần sử dụng | Tiết kiệm memory, boot nhanh | Chậm lần đầu sử dụng | MailServiceProvider |
| Singleton | Lần đầu resolve | Tiết kiệm tài nguyên, nhất quán | Có thể gây memory leak | Database connections |
6. Thực hành và Tips phỏng vấn¶
Câu hỏi thường gặp:¶
Q: Khác biệt giữa bind() và singleton()?
A:
- bind(): Mỗi lần resolve tạo instance mới
- singleton(): Chỉ tạo 1 instance duy nhất, các lần sau dùng lại
Q: Khi nào nên dùng Deferred Provider? A: Khi service không được sử dụng trong mọi request, ví dụ: Mail, Payment, External APIs
Q: register() và boot() khác nhau như thế nào?
A:
- register(): Chỉ đăng ký services, KHÔNG sử dụng services khác
- boot(): Có thể sử dụng các services đã được đăng ký
Code example cho phỏng vấn:¶
// Custom Service Provider
class PaymentServiceProvider extends ServiceProvider
{
protected $defer = true; // Lazy load
public function register()
{
// Đăng ký PaymentService
$this->app->bind('payment', function($app) {
return new PaymentService(
$app['config']['payment.gateway']
);
});
}
public function boot()
{
// Publish config files
$this->publishes([
__DIR__.'/config/payment.php' => config_path('payment.php')
]);
}
public function provides()
{
return ['payment']; // Services mà provider này cung cấp
}
}
7. Tổng kết¶
Laravel Lifecycle và Service Provider là nền tảng của framework:
- Container: Quản lý dependencies
- Service Provider: Cấu hình và đăng ký services
- Lifecycle: Quy trình xử lý từ request đến response