首先,让我们利用依赖注入来编写代码,而不考虑PHP-DI:

class Mailer{ public function mail($recipient, $content) { // send an email to the recipient }}

class UserManager{ private $mailer; public function __construct(Mailer $mailer) { $this->mailer = $mailer; } public function register($email, $password) { // The user just registered, we create his account // ... // We send him an email to say hello! $this->mailer->mail($email, 'Hello and welcome!'); }}

正如我们所看到的, UserManager 将 Mailer 作为布局器参数:这便是依赖注入!

2.创建容器

php推荐关系PHP 说话官方团队推举的依附注入对象 Vue.js

您可以非常轻松地创建一个为开拓预先配置的容器实例:

$container = new DI\Container();

如果你想注册定义文件(在PHP定义中阐明)或调度一些选项,你可以利用容器构建器:

$builder = new DI\ContainerBuilder();$builder->...$container = $builder->build();

3.创建工具

如果没有PHP-DI,我们将不得不像这样手动“连接”依赖项:

$mailer = new Mailer();$userManager = new UserManager($mailer);

相反,我们可以让PHP-DI找出依赖关系:

$userManager = $container->get('UserManager');

在后台,PHP-DI将创建一个Mailer工具和一个UserManager工具。

它怎么知道要注入什么?容器利用一种称为自动装置的技能。
这不是PHP-DI独占的,但这仍旧很棒。
它将扫描代码并查看布局函数中须要哪些参数。

在我们的示例中, UserManager 布局函数接管一个 Mailer 工具:PHP-DI知道它须要创建一个工具。
非常大略,但非常有效。

webman 框架运用

在webman里依赖自动注入是可选功能,此功能默认关闭。
如果你须要依赖自动注入,推举利用php-di,以下是webman结合php-di的用法。

安装

composer require psr/container ^1.1.1 php-di/php-di ^6 doctrine/annotations ^1.14

修正配置config/container.php,其终极内容如下:

$builder = new \DI\ContainerBuilder();$builder->addDefinitions(config('dependence', []));$builder->useAutowiring(true);$builder->useAnnotations(true);return $builder->build();

config/container.php里终极返回一个符合PSR-11规范的容器实例。
如果你不想利用 php-di ,可以在这里创建并返回一个其它符合PSR-11规范的容器实例。

布局函数注入

新建app/service/Mailer.php(如目录不存在请自行创建)内容如下:

<?phpnamespace app\service;class Mailer{ public function mail($email, $content) { // 发送邮件代码省略 }}

app/controller/UserController.php内容如下:

<?phpnamespace app\controller;use support\Request;use app\service\Mailer;class UserController{ private $mailer; public function __construct(Mailer $mailer) { $this->mailer = $mailer; } public function register(Request $request) { $this->mailer->mail('hello@webman.com', 'Hello and welcome!'); return response('ok'); }}

正常情形下,须要以下代码才能完成app\controller\UserController的实例化:

$mailer = new Mailer;$user = new UserController($mailer);

当利用php-di后,开拓者无需手动实例化掌握器中的Mailer,webman会自动帮你完成。
如果在实例化Mailer过程中有其它类的依赖,webman也会自动实例化并注入。
开拓者不须要任何的初始化事情。

把稳必须是由框架或者php-di创建的实例才能完成依赖自动注入,手动new的实例无法完成依赖自动注入,如需注入,须要利用support\Container接口更换new语句,例如:

use app\service\UserService;use app\service\LogService;use support\Container;// new关键字创建的实例无法依赖注入$user_service = new UserService;// new关键字创建的实例无法依赖注入$log_service = new LogService($path, $name);// Container创建的实例可以依赖注入$user_service = Container::get(UserService::class);// Container创建的实例可以依赖注入$log_service = Container::make(LogService::class, [$path, $name]);

表明注入

除告终构函数依赖自动注入,我们还可以利用表明注入。
连续上面的例子,app\controller\UserController变动成如下:

<?phpnamespace app\controller;use support\Request;use app\service\Mailer;use DI\Annotation\Inject;class UserController{ / @Inject @var Mailer / private $mailer; public function register(Request $request) { $this->mailer->mail('hello@webman.com', 'Hello and welcome!'); return response('ok'); }}

这个例子通过 @Inject 表明注入,并且由 @var 表明声明工具类型。
这个例子和布局函数注入效果一样,但是代码更精简。

把稳webman在1.4.6版本之前不支持掌握器参数注入,例如以下代码当webman<=1.4.6时是不支持的

<?phpnamespace app\controller;use support\Request;use app\service\Mailer;class UserController{ // 1.4.6版本之前不支持掌握器参数注入 public function register(Request $request, Mailer $mailer) { $mailer->mail('hello@webman.com', 'Hello and welcome!'); return response('ok'); }}

自定义布局函数注入

有时候布局函数传入的参数可能不是类的实例,而是字符串、数字、数组等数据。
例如Mailer布局函数须要通报smtp做事器ip和端口:

<?phpnamespace app\service;class Mailer{ private $smtpHost; private $smtpPort; public function __construct($smtp_host, $smtp_port) { $this->smtpHost = $smtp_host; $this->smtpPort = $smtp_port; } public function mail($email, $content) { // 发送邮件代码省略 }}

这种情形无法直策应用前面先容的布局函数自动注入,由于php-di无法确定$smtp_host $smtp_port的值是什么。
这时候可以考试测验自定义注入。

在config/dependence.php(文件不存在请自行创建)中加入如下代码:

return [ // ... 这里忽略了其它配置 app\service\Mailer::class => new app\service\Mailer('192.168.1.11', 25);];

这样当依赖注入须要获取app\service\Mailer实例时将自动利用这个配置中创建的app\service\Mailer实例。

我们把稳到,config/dependence.php 中利用了new来实例化Mailer类,这个在本示例没有任何问题,但是想象下如果Mailer类依赖了其它类的话或者Mailer类内部利用了表明注入,利用new初始化将不会依赖自动注入。
办理办法是利用自定义接口注入,通过Container::get(类名) 或者 Container::make(类名, [布局函数参数])方法来初始化类。