Service Providers
Overview
Service Providers are a convenient way to organize and register services within DomainFlow Core. They let you encapsulate logic for binding services, bootstrapping functionality, and optionally deferring expensive or optional features until needed. By grouping related services in a single provider, you keep your application tidy and make it simpler to manage multiple services at once.
Key Concepts
- Registration: A provider’s main job is to bind services into the application so they can be resolved when needed.
- Boot: Once registered, a provider can perform additional setup in its
boot()
method—especially useful if the provider needs to react to other services now being available. - Deferred Loading: If you mark a provider as deferred, it only registers its services on demand, improving startup performance for applications with many optional services.
Method Descriptions (Application-Level)
Below are the main methods on your Application instance to register, manage, and load service providers.
registerProvider($provider)
Signature
public function registerProvider(ServiceProviderInterface $provider): void
Purpose
Registers a service provider with the application. If the provider is not deferred, it immediately calls the provider’s register()
method. If the application has already booted, it then calls boot()
on the provider.
Parameter | Type | Required? | Description |
---|---|---|---|
$provider | ServiceProviderInterface | Yes | An object that implements the methods needed to register and optionally boot services. |
Usage Example
$app->registerProvider(new MyCustomServiceProvider());
unregisterProvider($providerClass)
Signature
public function unregisterProvider(string $providerClass): void
Purpose Removes a provider from the application, along with any deferred services it might have registered. This is helpful if you need to dynamically disable certain functionality.
Parameter | Type | Required? | Description |
---|---|---|---|
$providerClass | string | Yes | The fully qualified class name of the provider to remove. |
Usage Example
$app->unregisterProvider(\Acme\Example\ExampleServiceProvider::class);
getProviders()
Signature
public function getProviders(): array
Purpose Returns an array of all currently registered providers. You might use this for debugging or when you need to iterate over each provider for specialized logic.
Parameter | Type | Required? | Description |
---|---|---|---|
None | N/A | N/A | N/A |
Usage Example
foreach ($app->getProviders() as $provider) {
// Inspect or interact with the provider
}
loadDeferredProviders()
Signature
public function loadDeferredProviders(): void
Purpose Forces the application to register any providers marked as deferred—useful if you want everything loaded up front rather than waiting for on-demand resolution.
Parameter | Type | Required? | Description |
---|---|---|---|
None | N/A | N/A | N/A |
Usage Example
// If you want no lazy loading:
$app->loadDeferredProviders();
hasProvider($providerClass)
Signature
public function hasProvider(string $providerClass): bool
Purpose Checks if a particular provider is already registered. Useful to prevent multiple registrations or to confirm that a provider is active.
Parameter | Type | Required? | Description |
---|---|---|---|
$providerClass | string | Yes | The fully qualified class name of the provider to check for. |
Usage Example
if (!$app->hasProvider(\Vendor\Logging\LoggingProvider::class)) {
$app->registerProvider(new LoggingProvider());
}
Method Descriptions (Inside a Service Provider)
To create your own provider, you can implement the ServiceProviderInterface
or extend a base provider class. The interface typically expects you to define:
register($app)
Signature
public function register(Application $app): void
Purpose
Where you bind services into the application, e.g., $app->bind('SomeKey', ...)
. This method is called when the provider is first registered—either immediately or on-demand if deferred.
Parameter | Type | Required? | Description |
---|---|---|---|
$app | Application | Yes | Reference to the main application object |
boot($app)
Signature
public function boot(Application $app): void
Purpose
Runs after register()
—useful for tasks that rely on services being bound already. If the application is already booted when you register a provider, boot()
is called immediately after register()
completes.
Parameter | Type | Required? | Description |
---|---|---|---|
$app | Application | Yes | Reference to the main application object |
provides()
Signature
public function provides(): array
Purpose Returns an array of “service keys” that this provider is responsible for. When marked as deferred, the application uses this list to see if your provider should be loaded.
Parameter | Type | Required? | Description |
---|---|---|---|
None | N/A | N/A | Must return a list of string keys. |
isDeferred()
Signature
public function isDeferred(): bool
Purpose
Indicates whether your provider is eligible for lazy-loading (i.e., only loaded when one of its provides()
services is requested).
Parameter | Type | Required? | Description |
---|---|---|---|
None | N/A | N/A | Return true for lazy-loading. |
Comparative Descriptions
- Immediate vs. Deferred Registration
- If
isDeferred()
returnsfalse
,register()
happens right away. - If
true
, the provider’s services get bound only when their keys are first requested or if you explicitly callloadDeferredProviders()
. register()
vs.boot()
register()
is for binding or configuring services.boot()
is for tasks that rely on the services being fully registered, or for hooking into the application after it’s been initialized.
Practical Examples
class LoggingServiceProvider extends AbstractServiceProvider
{
public bool $defer = true; // This can be set to false for immediate loading
protected array $providedServices = [
'Logger'
];
public function register(Application $app): void
{
// Bind the service
$app->bind('Logger', function ($app) {
return new Logger(/* ... */);
});
}
public function boot(Application $app): void
{
// Possibly attach the logger to events or load additional config
}
}
// Usage in your app:
$app->registerProvider(new LoggingServiceProvider());
// If you want to load it immediately:
$app->loadDeferredProviders();
// Retrieve the logger:
$logger = $app->get('Logger'); // triggers deferred registration if not yet loaded
Extensibility
- Multiple Services per Provider: You can return many service keys in
provides()
. This makes it simple to group related services (e.g., “Mailer” and “MailQueue”). - Conditional Providers: Some teams use environment checks to decide whether to register certain providers. For instance, only register a debug provider if you’re in development mode.
- Plugin Systems: If your application supports add-ons, you can treat each add-on as a “service provider” that integrates new functionality without cluttering your core code.
Service providers keep your code organized and encourage modularity, making it easier to share or reuse common functionality across projects.