Small, lightweight and factory-biased service manager based on the PSR-11 standard.
You can install the package via composer:
composer require blackbonjour/service-manageruse BlackBonjour\ServiceManager\ServiceManager;
// Create a new service manager
$serviceManager = new ServiceManager();
// Add a service directly
$serviceManager->addService('config', [
'db' => [
'host' => 'localhost',
'user' => 'root',
'password' => 'secret',
],
]);
// Retrieve a service
$config = $serviceManager->get('config');The ServiceManager constructor accepts several configuration arrays:
$serviceManager = new ServiceManager(
services: [], // Pre-created service instances
factories: [], // Factories for creating services
abstractFactories: [], // Abstract factories for dynamic service creation
invokables: [], // Classes that can be instantiated directly
aliases: [], // Alternative names for services
);Services are pre-created instances that are stored in the container:
// Via constructor
$serviceManager = new ServiceManager([
'config' => ['debug' => true],
'logger' => new Logger(),
]);
// Via method
$serviceManager->addService('config', ['debug' => true]);
$serviceManager->addService('logger', new Logger());Factories are responsible for creating service instances. They can be:
- Classes implementing
FactoryInterface - Callable objects
- Class strings that resolve to one of the above
// Using a factory class
$serviceManager->addFactory(Database::class, DatabaseFactory::class);
// Using a callable
$serviceManager->addFactory('logger', function($container, $requestedName) {
return new Logger();
});
// Via constructor
$serviceManager = new ServiceManager(
factories: [
Database::class => DatabaseFactory::class,
'logger' => function($container, $requestedName) {
return new Logger();
},
]
);Abstract factories are used when a service is not explicitly defined. They determine if they can create a requested service:
// Add an abstract factory
$serviceManager->addAbstractFactory(new DynamicFactory());
// Or via constructor
$serviceManager = new ServiceManager(
abstractFactories: [
new DynamicFactory(),
ReflectionFactory::class,
]
);Invokables are classes that can be instantiated directly without a factory:
// Add an invokable
$serviceManager->addInvokable(stdClass::class);
// Via constructor
$serviceManager = new ServiceManager(
invokables: [
stdClass::class,
SomeClass::class,
]
);Aliases provide alternative names for services:
// Add an alias
$serviceManager->addAlias('configuration', 'config');
// Via constructor
$serviceManager = new ServiceManager(
aliases: [
'configuration' => 'config',
'db' => Database::class,
]
);You can create services with additional options:
// Define a factory that accepts options
$serviceManager->addFactory('database', function($container, $requestedName, $options = null) {
return new Database(
$options['host'] ?? 'localhost',
$options['user'] ?? 'root',
$options['password'] ?? 'secret'
);
});
// Create the service with options
$db = $serviceManager->createService('database', [
'host' => 'db.example.com',
'user' => 'admin',
'password' => 'password123'
]);The ServiceManager implements ArrayAccess, allowing you to use array syntax:
// Add a service
$serviceManager['config'] = ['debug' => true];
// Check if a service exists
if (isset($serviceManager['config'])) {
// Service exists
}
// Get a service
$config = $serviceManager['config'];
// Remove a service
unset($serviceManager['config']);You can remove services from the container:
$serviceManager->removeService('config');
// or
unset($serviceManager['config']);The DynamicFactory looks for a factory class with the same name as the requested service plus "Factory":
// Add the DynamicFactory
$serviceManager->addAbstractFactory(new DynamicFactory());
// Now if you request MyService, it will look for MyServiceFactory
$service = $serviceManager->get(MyService::class);The ReflectionFactory uses PHP's Reflection API to automatically instantiate classes and resolve their dependencies:
// Add the ReflectionFactory
$serviceManager->addAbstractFactory(new ReflectionFactory());
// Now you can get any class that has constructor dependencies registered in the container
$service = $serviceManager->get(MyService::class);The main container class implementing PSR-11's ContainerInterface.
Methods:
__construct(array $services = [], array $factories = [], array $abstractFactories = [], array $invokables = [], array $aliases = [])addAbstractFactory(AbstractFactoryInterface|string $abstractFactory): voidaddAlias(string $alias, string $id): voidaddFactory(string $id, FactoryInterface|callable|string $factory): voidaddInvokable(string $id): voidaddService(string $id, mixed $service): voidcreateService(string $id, ?array $options = null): mixedget(string $id): mixedhas(string $id): boolremoveService(string $id): void
Interface for factories that create services.
Methods:
__invoke(ContainerInterface $container, string $service, ?array $options = null)
Interface for abstract factories that can dynamically determine if they can create a service.
Methods:
canCreate(ContainerInterface $container, string $service): bool__invoke(ContainerInterface $container, string $service, ?array $options = null)(inherited from FactoryInterface)
A factory for creating instances of classes without dependencies.
Methods:
__invoke(ContainerInterface $container, string $service, ?array $options = null)