服务提供者及门面
一.编写一个服务提供类
class Test { public function hello() { echo 'hello world'; } }
二.服务提供者
1.生成
artisan make:provider TestServiceProvide
2.生成后的代码:
class TestServiceProvide extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { } }
3.在register中可以绑定服务和对应的类,或者将一个接口绑定到一个类,有三种方法:
a.绑定一个实例:
$instance = new Test(); $this->app->instance('TestServiceProvider', $instance);
b.bind
如果不需要自动依赖,也可以new Test;使用app()帮助函数解决了自动依赖
$this->app->bind('TestServiceProvider', function($app) { return app(Test::class); });
或者
$this->app->bind('TestServiceProvider', Test::class);
如果将bind的第三个参数设置为true,即为共享模式;也就是绑定的服务对应的类是一个单例模式;默认为false
c.绑定一个单例:
$this->app->singleton('TestServiceProvider', Test::class); //也可以使用闭包或new Test
以上绑定中,TestServiceProvider就是这个服务的名字,后面的指明了有那个类来提供服务.这个服务的名字可以随便取,调用服务名字的时候,再去取到对应的类实现.如果这个服务名是一个接口,那么就可以实现依赖注入.
三.注册服务
1.在app/config.php下的providers数组中,添加
Test\Providers\TestServiceProvide::class
2.在providers中的AppServiceProvider.php的register方法中添加(这种方式更适合按需加载服务提供者):
$this->app->register(TestServiceProvide::class);
四.延迟绑定服务
如果服务不是每次加载都需要,可以提供延迟绑定,在需要的时候再绑定
class TestServiceProvide extends ServiceProvider { protected $defer = true; /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { $this->app->singleton('TestServiceProvider', Test::class); } public function provides() { return ['Test']; } }
五.控制器或其他地方调用
1.依赖注入
2.app('TestServiceProvider')
六.门面(Facades)
1.门面简化了服务在应用的调用方式,以一种看起来像是静态调用的方式来简化调用,如
Auth::id(),Auth::check()等;
2.我们看看来如何建立一个门面
a.建立一个门面类,继承Facade,重写getFacadeAccessor方法
class TestFacade extends Facade { protected static function getFacadeAccessor() { // 返回一个服务提供者 return 'TestServiceProvider'; } }
b.在app/config.php的aliases添加:
... 'MyTest' => Test\Facades\TestFacade::class, //MyTest是门面的名字,随便取
3.使用
use MyTest; .............. .............. ......... MyTest::hello(); .........
需要说明的是门面对应的服务提供者将实现的是一个单例服务.
总结:
总体而言,如果你不做第三方应用,不做全局的操作,不做接口到类的依赖注入.其实没有必要使用服务提供者.而门面仅仅是对服务调用方式的一种包装罢了.