从百草园到三味书屋 (四)服务提供者

Service Providers 服务提供者

  1. 一个Laravel服务提供者就是一个用来进行IoC绑定的类。

  2. 事实上,Laravel有好几十个服务提供者,用于管理框架核心组件的容器绑定。

  3. 几乎框架里每一个组件的IoC绑定都是靠服务提供者来做的。

  4. 你可以在app/config/app.php这个文件里查看目前有哪些服务提供者。

As Bootstrapper 他是引导程序

  1. 一个服务提供者必须有一个register方法。你可以在这个方法里写IoC绑定。

  2. 当一个请求发过来,程序框架刚启动时,所有在你配置文件里的服务提供者的register方法就会被调用。

    3.这在程序周期的很早的地方就会执行,所以在你自己的引导代码(比如那些在start目录里的文件)里所有的服务已经准备好了。

Register Vs. Boot 注册 Vs 引导代码

  1. 永远不要在register方法里面使用任何服务。
  2. 该方法只是用来进行IoC绑定的地方。
  3. 所有关于绑定类后续的判断、交互都要在boot方法里进行。

Deferred Providers 延迟加载的服务提供者

  1. 并非在你配置文件中的providers数组里的所有提供者在每次请求都会被实例化。
  2. 否则会对性能不利,尤其是这个服务的功能用不到的情况下。
  3. 比如,QueueServiceProvider服务就不是每次都用得到。

为了达到只实例化需要的服务的提供者,Laravel生成了“服务清单”并且储存在了app/storage/meta目录下。这份清单列出了应用里所有的服务提供者,包括容器绑定的名字也记录了。这样,当应用想让容器取出一个名为queue的绑定时,Laravel知道需要先实例化并运行QueueServiceProvider因为在服务清单里记录着该服务提供者能提供queue的绑定。如此这般框架就能够延迟加载每个请求需要的服务了,性能大大提高。

As Organizer 作为管理工具

你应用的“启动”文件都储存在app/start目录下。根据不同的请求入口,系统会载入不同的启动文件。在全局的start.php文件加载后,系统会根据执行环境的不同来加载不同的启动文件。 此外,在执行命令行程序时,artisan.php文件会被载入。

也许我们的应用正在使用Pusher 来为客户推送消息。为了将我们的应用和Pusher解耦,我们要定义EventPusherInterface接口和对应的实现类PusherEventPusher。这样在需求变化或应用改进时,我们就可以随时轻松的改变推送服务提供商。

interface EventPusherInterface{
    public function push($message, array $data = array());
}

class PusherEventPusher implements EventPusherInterface{
    public function __construct(PusherSdk $pusher)
    {
        $this->pusher = $pusher;
    }
    public function push($message, array $data = array())
    {
        // Push message via the Pusher SDK...
    }
}

//接下来我们创建一个EventPusherServiceProvider:
use Illuminate\Support\ServiceProvider;
class EventPusherServiceProvider extends ServiceProvider {
    public function register()
    {
        $this->app->singleton('PusherSdk', function()
        {
            return new PusherSdk('app-key', 'secret-key');
        }
        $this->app->singleton('EventPusherInterface', 'PusherEventPusher');
    }
}

很好! 我们对事件推送进行了清晰的抽象,同时我们也有了一个很不错的地方进行注册、绑定其他相关的东西到容器里。最后一步只需要将EventPusherServiceProvider写入app/config/app.php文件内的providers数组里就可以了。现在这个应用里的EventPusherInterface已经被绑定到了正确的实现类上。

Should You Singleton? 要使用单例么?

用不用单例可以这样来考虑:如果在一次请求周期中该类只需要有一个实例,就使用singleton;否则就使用bind。

Booting Providers 服务提供者的启动过程

在所有服务提供者都注册以后,他们就进入了“启动”过程。该过程会触发每个服务提供者的boot方法。这里会发生一种常见的错误用法:在register方法里面调用其他的服务。由于在register方法里我们不能保证所有其他服务都已经被加载,所以在该方法里调用别的服务有可能会出错。所以如果你想在服务提供者里调用别的服务,请在boot方法里做这种事儿。register方法只能进行容器注册。

在启动方法里面,你想做什么都可以:注册事件监听,引入路由文件,注册过滤器,或者其他你能想象到的事儿。再强调一下,要发挥服务提供者的管理功能。可能你想将相关的多个事件监听归为一组?将他们放到一个服务提供者的boot方法里,这会很管用的!或者你也可以引入单独的“events”、“routes”PHP文件:

public function boot()
{
require_once __DIR__.'/events.php';
require_once __DIR__.'/routes.php';
}

Providing The Core 核心也是服务提供者的模式

理解Laravel核心的最好方法是去读它的核心服务源码。如果你对这些服务的源码、容器注册等都很熟悉,那么你对Laravel是如何工作的将会有十分深刻的理解。

大部分的服务提供者是延迟加载的,意味着并非所有请求都会调用到他们;然而有一些很基础的服务是每一次请求都会被加载的,比如FilesystemServiceProvide和ExceptionServiceProvider。有人会说核心服务提供者和应用程序容器就是Laravel。Laravel 其实是将这么多不同部分联系起来,形成一个单一的、内聚的整体的这么一个机制。拿建筑来比喻,那些服务提供者就是框架的预制模块。

原文链接:https://my.oschina.net/zgldh?tab=newest&am...

本作品采用《CC 协议》,转载必须注明作者和本文链接
写的不好,就当是整理下思绪吧。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!