Minor【 PHP框架】4.服务容器与服务提供者
框架Github地址:github.com/Orlion/Minor
(如果觉得还不错给个star哦(^-^)V)
框架作者: Orlion
知乎:https://www.zhihu.com/people/orlion
Github: https://github.com/Orlion
关于服务容器可以参考我的另外一篇文章:http://www.cnblogs.com/orlion/p/4797422.html
Minor使用IoC(Inversion of Control,控制倒转,这是一个设计模式,可以先查看下百科)容器这个强有力的工具管理类依赖。依赖注入(也是一种设计模式,一般用于实现IoC)是 一个不用编写固定代码来处理类之间依赖的方法,相反的,这些依赖是在运行时注入的,这样允许处理依赖时具有更大的灵活性。
服务提供者是服务容器中的单元,是一个普通的类,任何类都可以被注册为服务,前提是这个类的依赖可以被服务容器解析而且必须有一个boot()方法用于服务容器自动注入该服务提供者需要的依赖。(例如循环依赖就可能会导致应用异常)。
可以在app/Lib/目录下或者是其他任何app目录下创建一个服务提供者类:
<?php namespace App\Lib; class MailProvider { private $from; private $username; private $password; public function boot($from, $username, $password) { $this->from = $from; $this->username = $username; $this->password = $password; } public function send($to) { echo '[MailProvider] send email from ' . $this->from . ' to ' . $to . ' use username:' . $this->username . ' and password:' . $this->password . '<br/><br/>'; } }
这个服务提供者提供了一个发送邮件的服务,它的boot方法指明了这个类需要$from\$username\$password三个依赖。注意:服务提供者的构造函数不能带有参数,因为服务容器在实例化服务提供者时并不会根据构造方法的参数去解析依赖。
上一步定义好了一个服务提供者,这一步就需要将这个服务提供者注册到App中
打开app/Config/providers.php文件,添加一下内容:
<?php return [ 'mailer' => [ 'class' => 'App\\Lib\\MailProvider', 'arguments' => ['orlionml@gmail.com', 'username', 'password'], 'singleton' => true, ], ];
class指的就是这个服务提供者的全名。这里你也可以指定一个匿名函数例:
'test' => [ 'class' => function(){ $mail = new App\...\Mail; $mail->boot('...', '...' ,'...'); return $mail; } ],
arguments指的就是服务提供者的boot方法需要的参数。假如你的服务提供者依赖于另外一个依赖,你也可以使用'@serviceName'的语法来注入一个依赖,例Shop类依赖Mail:
<?php return [ 'mailer' => [ 'class' => 'App\\Lib\\MailProvider', 'arguments' => ['orlionml@gmail.com', 'username', 'password'], 'singleton' => true, ], 'shop' => [ 'class' => 'App\\Lib\\Shop', 'arguments' => ['@mailer'], ], ];
singleton表示每次从服务容器中取出这个服务时都是同一个对象(单例),如果设置为false则每次都会重新创建这个服务。
将服务注册到App中后就可以通过服务容器(Minor\Ioc\ServiceContainer)的get($serviceName)方法来获取这个服务了,在控制器中可以这样获取一个上边我们的"mailer"服务:
class HelloController extends Controller { public function hello() { $container = $this-app->getServiceContainer(); $mail = $container->get('mailer'); $mail->send('somemsg'); ... } }
服务容器的初始化是在App的初始化时,即public/index.php文件中
$app = \Minor\Framework\App::getInstance( ... $providers = require APP_DIR . 'Config/providers.php', ... );
这样你就可以通过调用App的getServiceContainer()方法来获取服务容器。
class HelloController extends Controller { public function hello() { $container = $this-app->getServiceContainer(); ... } }