Service Providers
Service Providers for bootstrapping services and registering bindings in Container
Service Providers are classes that bootstrap services and dependencies in Laravel. They are the central point for bootstrapping application and manage all configuration, binding, and initialization logic.
Two Main Methods:
1. register(): For registering bindings in Service Container. This method should only do binding and not use other services because they may not be registered yet.
2. boot(): For accessing other services and performing configurations. This method runs after all providers are registered, so you can access other services.
Deferred Providers: Some Providers are only loaded when actually needed, not on every request. This is suitable for rarely used or resource-intensive services.
Uses:
- Register bindings in Service Container
- Register routes and route groups
- Register view composers and view creators
- Register event listeners and subscribers
- Configure packages and third-party services
- Register middleware and middleware groups
- Configure database connections
- Register custom validation rules
Examples
Creating Service Provider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class PaymentServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('PaymentGateway', function ($app) {
return new StripePaymentGateway();
});
}
public function boot()
{
// Access other services here
}
}
A simple Service Provider that registers PaymentGateway as singleton.
Service Provider with Route Registration
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Route;
class ApiServiceProvider extends ServiceProvider
{
public function register()
{
// Register bindings
}
public function boot()
{
Route::prefix('api')
->middleware('api')
->namespace('App\Http\Controllers\Api')
->group(base_path('routes/api.php'));
}
}
In boot() you can register routes.
Service Provider with View Composers
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
class ViewServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer('layouts.app', function ($view) {
$view->with('categories', Category::all());
});
View::composer('*', function ($view) {
$view->with('currentUser', auth()->user());
});
}
}
You can register view composers in boot().
Service Provider with Event Listeners
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Events\OrderCreated;
use App\Listeners\SendOrderConfirmation;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
OrderCreated::class => [
SendOrderConfirmation::class,
],
];
public function boot()
{
Event::listen(OrderCreated::class, SendOrderConfirmation::class);
}
}
You can register event listeners in boot().
Service Provider with Middleware Registration
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Http\Kernel;
class MiddlewareServiceProvider extends ServiceProvider
{
public function boot(Kernel $kernel)
{
$kernel->pushMiddleware(\App\Http\Middleware\CustomMiddleware::class);
$kernel->prependMiddleware(\App\Http\Middleware\FirstMiddleware::class);
$kernel->appendMiddlewareToGroup('web', \App\Http\Middleware\WebMiddleware::class);
}
}
You can register middleware in boot().
Service Provider with Custom Validation Rules
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class ValidationServiceProvider extends ServiceProvider
{
public function boot()
{
Validator::extend('phone', function ($attribute, $value, $parameters, $validator) {
return preg_match('/^[0-9]{10}$/', $value);
});
Validator::replacer('phone', function ($message, $attribute, $rule, $parameters) {
return str_replace(':attribute', $attribute, 'The :attribute must be a valid phone number.');
});
}
}
You can register custom validation rules in boot().
Service Provider with Database Configuration
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\DB;
class DatabaseServiceProvider extends ServiceProvider
{
public function boot()
{
DB::listen(function ($query) {
// Log all queries in development
if (app()->environment('local')) {
Log::info($query->sql, [
'bindings' => $query->bindings,
'time' => $query->time
]);
}
});
// Set connection timeout
config(['database.connections.mysql.options.connect_timeout' => 10]);
}
}
You can configure database in boot().
Conditional Service Provider Registration
<?php
// In config/app.php
'providers' => [
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// Conditional registration
...(app()->environment('local') ? [
App\Providers\DebugServiceProvider::class,
] : []),
],
// Or in Service Provider itself
class ConditionalServiceProvider extends ServiceProvider
{
public function register()
{
if ($this->app->environment('production')) {
$this->app->singleton('Service', ProductionService::class);
} else {
$this->app->singleton('Service', DevelopmentService::class);
}
}
}
You can conditionally register service providers.
Use Cases
- Registering bindings for dependency injection
- Registering routes for modular architecture
- Configuring third-party packages
- Registering event listeners and subscribers
- Registering view composers for shared data
- Registering custom validation rules
- Configuring database connections
- Registering middleware and middleware groups
Common Mistakes
- Using services in register() that haven't been registered yet
- Performing heavy operations in register() causing slow bootstrap
- Forgetting to register provider in config/app.php
- Using boot() for binding which should be in register()
- Not using deferred providers for rarely used services
- Registering routes in register() instead of boot()
Best Practices
- In register() only do binding
- Use boot() to access other services
- Use deferred providers for rarely used services
- Keep providers modular and focused
- Use conditional registration for environment-specific providers
- Document providers
- Use service provider discovery for packages
Edge Cases
- Circular dependency in service providers
- Provider that throws exception in register()
- Deferred provider that never loads
- Provider requiring HTTP context
- Provider in queue jobs which have different container instance
Performance Notes
- Using deferred providers can reduce bootstrap time
- Registering binding in register() is faster than boot()
- Provider discovery in Laravel 11.x has performance improvements
- Use conditional registration to reduce provider count
- Perform heavy operations in boot(), not register()
Security Notes
- Ensure providers follow security best practices
- Use conditional registration for security-sensitive providers
- Ensure sensitive bindings are properly done
Interview Points
- What is the difference between register() and boot()?
- When should you use deferred provider?
- How can you register a service provider?
- What should be done in register() and what in boot()?
- What are the benefits of using service providers?
- How can you do conditional provider registration?
Version Notes
- Laravel 11.x: Improved performance in provider loading
- Laravel 11.x: Better support for provider discovery
- Laravel 10.x: Improved deferred provider resolution
- Laravel 9.x: Improved provider caching