cee / simple-di
该软件包最新版本(v1.0)没有可用的许可证信息。
简单的依赖注入容器
v1.0
2017-10-12 07:07 UTC
Requires (Dev)
- phpunit/phpunit: ^5.6
This package is not auto-updated.
Last update: 2024-09-19 19:12:37 UTC
README
简单的依赖注入容器
适用于构建服务类依赖树的工具。服务类是一个在应用中只有一个实例的类。它可以用作Nette Di容器的简单替代品。所有DI容器的配置都是用PHP语言完成的。
基本用法
$container = new Cee\SimpleDi\Container(); $classInstance = $container->createServiceOnce('ClassName');
使用接口作为依赖的示例
interface Logger { public function log($message); }
interface Mailer { public function send($message, $subject, $to); }
提供某些功能并依赖于先前接口的Service类
class NotificationService { private $mailer; private $logger; public function __construct(Mailer $mailer, Logger $logger) { $this->mailer = mailer; $this->logger = logger; } public function notify($message, array $recipients) { $subject = 'Notification'; foreach ($recipients as $recipient) { $this->mailer->send($message, $subject, $recipient); } $this->logger->log(...); } }
接口的实现
class ErrorLogLogger extends Logger { public function log($message) { error_log('Error: ' . $message); } }
class SendMailMailer extends Mailer { public function send($message, $subject, $to) { mail($to, $subject, $message); } }
最后是配置Simple DI容器和创建的NotificationService
实例
$container = new Cee\SimpleDi\Container(); $container->setInterfaceImplementation(Logger::class, ErrorLogLogger::class); $container->setInterfaceImplementation(Mailer::class, SendMailMailer::class); $notificationService = $container->createServiceOnce(NotificationService::class);
Simple Di容器通过类型提示(使用PHP反射)填充参数。这被称为自动装配。
在服务类构造函数中没有类型提示参数的示例
class NotificationService { private $mailer; private $logFileName; public function __construct(Mailer $mailer, $logFileName) { $this->mailer = mailer; $this->logFileName = logFileName; } public function notify($message, array $recipients) { $subject = 'Notification'; foreach ($recipients as $recipient) { $this->mailer->send($message, $subject, $recipient); } file_put_contents($logFileName, ...); } }
作为Simple DI容器扩展类的容器配置
namespace App; class Container extends \Cee\SimpleDi\Container { public function __construct($logFileName) { $notificationService = new \NotificationService(new SendMailMailer(), $logFileName); $this->addServiceInstance($notificationService); } }
在应用程序中我们使用自己的容器
$logFileName = 'log.txt'; $container = new App\Container($logFileName); $notificationService = $container->createServiceOnce(NotificationService::class);
这个示例的缺点是NotificationService
是在应用程序启动时创建的,而不是按需创建,就像其他由Simple DI容器创建的服务类。这对于不需要重构代码的旧代码很有用。但重构的目标是在服务类的所有无类型提示参数上创建包装器。在这种情况下,第一步是
class NotificationService { private $mailer; private $logFileName; public function __construct(Mailer $mailer, LogFileName $logFileName) { ...
之后,您不需要自己创建NotificationService。下一步是创建服务类Logger,就像示例中使用接口那样。
使用已创建的类的示例
典型用例是具有单例的旧代码,或者如果您需要进行逐步重构。在您可以启动DI容器之前,您已经有服务类的实例。您需要使用该类的自动装配将其用于其他类。
class Repository { public function __construct(MySqlConnector $mySqlConnector) { ... }
class Container extends \Cee\SimpleDi\Container { public function __construct(MySqlConnector $mySqlConnector) { $this->addServiceInstance($mySqlConnector); } }
并且它工作正常
$mySqlConnector = MySqlConnector::instance(); $container = new App\Container($mySqlConnector); $repository = $container->createServiceOnce(Repository::class);