rafaeltovar / php-service-manager
简单、轻量级、PHP 的最小化服务管理器和依赖注入。
v1.0.4
2020-10-29 13:39 UTC
Requires
- php: >=7.0
- psr/container: ^1.0
README
简单、轻量级、PHP 的最小化服务管理器和依赖注入。
安装
Composer
执行
composer require rafaeltovar/php-service-manager
功能
- 依赖注入
- 服务容器
- 提供者
- 单例策略
- 仅在服务被调用时初始化
- 别名
文档
服务容器
服务容器 是管理服务队列的主要服务控制器。
// myproject.php use MyServiceAProvider; $serviceContainer = new \ServiceManager\ServiceContainer( [MyServiceAProvider::class] );
服务提供者
这是我的服务。
// MyServiceA.php class MyServiceA { public function test() { echo "Working."; } }
这是我的服务 提供者。
// 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(); } }
向提供者传递自定义参数
有时我们需要向提供者传递一些参数以初始化服务,例如配置或记录器,在这种情况下,我们需要实现 \ServiceManager\ServiceProviderArgumentsInterface
。
MyCustomArguments
将拥有它需要的参数。
// 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; } }
带有参数的示例服务
// 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); } }
示例服务提供者
// 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.
自定义构建器
有时我们的控制器需要其他控制器或数据,而不是服务。在这些情况下,我们可以创建一个自定义构造函数实现 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") ); } }
现在我们可以构建我们的控制器。如果实现了 ControllerBuilderCreateInterface
,服务容器将调用 create
方法。
use MyController; //... $myCtrl = $serviceContainer->build(MyController::class);
别名
有时我们需要处理接口,我们可以使用别名来获取实现这些接口的服务。
// 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; } }
现在我们可以使用接口依赖来构建我们的控制器。
// 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);