Simple, light, minimum service manager and dependency injection for PHP.
Execute:
composer require rafaeltovar/php-service-manager
- Dependency injection
- Service container
- Providers
- Singleton strategy
- Initialized only if service is called
- Alias
The service container is the main service controller for manage the service queue.
// myproject.php
use MyServiceAProvider;
$serviceContainer = new \ServiceManager\ServiceContainer(
[MyServiceAProvider::class]
);
This is my service.
// MyServiceA.php
class MyServiceA
{
public function test()
{
echo "Working.";
}
}
This is my service provider.
// MyServiceAProvider.php
class MyServiceAProvider
extends \ServiceManager\ServiceProvider
{
/**
* This method return the service class name (mandatory)
**/
public function getServiceType() : string
{
return MyServiceA::class;
}
/**
* This method return the identification of the service
* into Service Container (mandatory)
**/
public function getServiceId(): string
{
return "my-service-a";
}
/**
* This method return the service (mandatory)
**/
public function getService()
{
return new MyServiceA();
}
}
Sometimes We need pass some arguments to the provider for initialize the service, like the config or logger, for example. In this case we need implements \ServiceManager\ServiceProviderArgumentsInterface
.
MyCustomArguments
will have the arguments it needs.
// myproject.php
use MyServiceDebugProvider,
MyServiceAProvider;
use MyCustomArguments;
//...
$serviceContainer = new \ServiceManager\ServiceContainer(
[
MyServiceAProvider::class,
MyServiceDebugProvider::class
],
[],
new MyCustomArguments($myLogger)
);
// MyCustomArguments.php
class MyCustomArguments
implements \ServiceManager\ServiceProviderArgumentsInterface
{
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger;
}
public function getLogger() : \Psr\Log\LoggerInterface
{
return $this->logger;
}
}
My example service with argument:
// MyServiceDebug.php
class MyServiceDebug
{
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger;
}
public function write(string $text)
{
$this->logger->debug($text);
}
}
My example service provider:
// MyServiceDebugProvider.php
class MyServiceDebugProvider
extends \ServiceManager\ServiceProvider
{
public function getServiceType() : string
{
return MyServiceDebug::class;
}
public function getServiceId(): string
{
return "debug";
}
public function getService()
{
$logger = $this->getProviderArguments()->getLogger();
return new MyServiceDebug($logger);
}
}
$serviceContainer->get("my-service-a")->test();
// result:
Working.
// MyController.php
class MyController
{
protected $a;
public function __construct(MyServiceA $a)
{
$this->a = $a;
}
public function test()
{
$this->a->test();
}
}
use MyController;
//...
$myCtrl = $serviceContainer->build(MyController::class);
$myCtrl->test();
// result:
Working.
Sometime our controller need other controller or data, not a service. In those cases we can create a custom constructor implements ControllerBuilderCreateInterface
.
// MyController.php
use ServiceManager\ServiceContainer,
ServiceManager\ControllerBuilderCreateInterface;
class MyController
implements ControllerBuilderCreateInterface
{
protected $public;
public function __construct(string $publicFolder)
{
$this->public = $publicFolder;
}
public static function create(ServiceContainer $services)
{
return new MyController(
$services->get('config')->get("PUBLIC_FOLDER")
);
}
}
Now we can build our controller. The service container will call to create
method if implements ControllerBuilderCreateInterface
.
use MyController;
//...
$myCtrl = $serviceContainer->build(MyController::class);
Other times we need to work with interfaces, we can use aliases to obtain the services that implement these interfaces.
// myproject.php
use MyServiceDebugProvider,
MyServiceAProvider;
use MyCustomArguments;
//...
$serviceContainer = new \ServiceManager\ServiceContainer(
[
MyLoggerProvider::class,
],
[ // aliases
// interface => service id
\Psr\Log\LoggerInterface::class => "logger"
]
);
// MyServiceDebugProvider.php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
class MyLoggerProvider
extends \ServiceManager\ServiceProvider
{
public function getServiceType() : string
{
return Logger::class;
}
public function getServiceId(): string
{
return "logger";
}
public function getService()
{
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
return $log;
}
}
Now we can build our controller with interface dependency.
// MyController.php
class MyController
{
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger; // this logger will be \Monolog\Logger
}
// ...
}
use MyController;
//...
$myCtrl = $serviceContainer->build(MyController::class);