rafaeltovar/php-service-manager

简单、轻量级、PHP 的最小化服务管理器和依赖注入。

v1.0.4 2020-10-29 13:39 UTC

This package is auto-updated.

Last update: 2024-09-29 05:28:13 UTC


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);