服务提供者


定义

服务提供者就是,当前应用需要哪些服务/组件,我们就在服务提供者里面定义哪些服务/组件,方便在程序里面直接使用,解决了类与类之间的耦合

存放位置

可以在任意位置建立服务提供者,我们推荐在 /common/provider 目录下新建服务提供者类,服务提供者类必须继承Timo\Support\ServiceProvider, 我们只需在类的register方法里面注册服务即可,看下面的例子 服务提供者可以是多个,我们可以使用服务提供者下面的$container(服务容器实例)属性来注册服务

新建服务提供者

创建一个空的服务提供者CommonProvider,意思就是没有注册任何一个服务,路径:

  1. /common/provider/CommonProvider

  1. <?php
  2. namespace common\provider;
  3. class CommonProvider extends ServiceProvider
  4. {
  5. public function register()
  6. {
  7. }
  8. }

注册服务

  1. 注册服务只需在register方法里面注册服务即可,注册方式有很多种

方式一,普通注册,通过get获取服务时,获取到的都是全新服务实例

  1. $this->container->bind();

方式二,单例模式注册,通过get获取服务时,获取到的都是同一个服务器实例

  1. $this->container->singleton();

方式三,注册一个服务器实例

  1. $this->container->instance();

举例说明

  1. <?php
  2. namespace common\provider;
  3. use lib\markdown\Markdown;
  4. use Timo\Support\ServiceProvider;
  5. class CommonProvider extends ServiceProvider
  6. {
  7. public function register()
  8. {
  9. $this->container->bind([Car::class => 'car'], function() {
  10. return new Car();
  11. });
  12. $this->container->singleton('markdown', Markdown::class);
  13. $this->container->singleton('markdown', 'lib\markdown\Markdown');
  14. $this->bind(['lib\pay\Client' => 'pay'], function($container) {
  15. $car = $container->get('car');
  16. return new Client($car);
  17. });
  18. }
  19. }

上面我们注册了一个名为car的服务,并且是以单例的模式注册的,可以在register方法里面注册多个服务

服务别名

  1. namespace common\provider;
  2. use lib\markdown\Markdown;
  3. use Timo\Support\ServiceProvider;
  4. class CommonProvider extends ServiceProvider
  5. {
  6. public function register()
  7. {
  8. //说明 Markdown::class 等于 'lib\markdown\Markdown' , 服务别名就是markdown
  9. $this->container->singleton([Markdown::class => 'markdown'], Markdown::class);
  10. }
  11. }

注册服务提供者

我们要告诉框架有哪些服务提供者

  1. 可以在配置文件中providers项定义服务提供者,可注册多个
  1. 'providers' => [
  2. app\provider\CommonProvider::class,
  3. app\provider\PayProvider::class,
  4. app\provider\Ossprovider::class
  5. ]

怎样获取服务容器实例

  1. 我们要在其它类里面使用服务容器,该怎么获取呢?
  2. $container = App::container();
  3. 比如,我们要在控制器里面使用,我们可以放到所有控制器的基类里面,比如BaseCommon控制器
  1. namespace app\web\controller;
  2. use Timo\Core\Controller;
  3. class Base extends Controller
  4. {
  5. protected $container;
  6. public function __construct()
  7. {
  8. parent::__construct();
  9. $this->container = App::container();
  10. }
  11. }
  1. 然后,我们就可以在其它控制器里面方便的使用了
  1. php
  2. namespace app\web\controller;
  3. use app\web\model\DocumentModel;
  4. use lib\markdown\Markdown;
  5. use Timo\Core\Exception;
  6. use Timo\Core\Request;
  7. class Document extends Common
  8. {
  9. /**
  10. * 文档详情页
  11. *
  12. * @param int $id
  13. * @return string
  14. * @throws Exception
  15. */
  16. public function show($id = 0)
  17. {
  18. $id = (int) $id;
  19. if ($id <= 0) {
  20. throw new Exception('文档ID不能小于零');
  21. }
  22. //获取文档标题
  23. $document = (new DocumentModel())->getDocument($id);
  24. if (!$document) {
  25. throw new Exception('文档'.$id.'不存在');
  26. }
  27. //获取文档内容
  28. /**
  29. * @var $markdown Markdown
  30. */
  31. $markdown = $this->container->get('markdown');
  32. $doc_html = $markdown->makeHtmlFragment('document', $id, false);
  33. $this->assign('title', $document['title']);
  34. $this->assign('doc', $doc_html);
  35. return $this->render();
  36. }
  37. }