资讯专栏INFORMATION COLUMN

Laravel深入学习4 - 服务提供器

daryl / 1303人阅读

摘要:一个服务提供器必须包含至少一种方法。服务提供器一旦被注册,就可被用于程序的各个地方。注意服务提供器的变量来自类中。启动服务当所有的服务提供器注册之后,他们就变成了已启动状态。再次提示,把服务提供器作为一种组织工具来使用。

声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理解翻译,肯定会有错误的地方,欢迎指正。

欢迎转载,转载请注明出处,谢谢!

服务提供器 启动引导

Laravel服务提供器是往IoC容器中绑定服务的类。事实上,框架核心就是由很多这样的服务提供器驱动管理着容器中绑定的各种资源。基本上框架中的所有组件都是以这种使用提供器注入资源到容器的方式进行注册的。从项目文件app/config/app.php中的providers数组中可以浏览到当前项目使用的提供器列表。

一个服务提供器必须包含至少一种方法:registerregister方法中实现了类绑定到容器的逻辑。当用户发起一个请求时,框架启动,配置文件中定义的服务提供器的register方法会被执行。这在Laravel执行生命周期的早期就会触发,所以,当你的启动文件、比如start目录中的文件加载之后,这些服务启动器就已经可用了。

注册 vs 启动

不要试图在register方法中使用提供器服务。他只是为了将对象绑定到容器中来使用的。所有关于绑定类的后续操作都应在boot方法中完成的。

一些通过Composer安装的第三方类库,都是通过服务提供器进行注入的。类库的安装说明会明确的让你在配置文件中通过向providers数组方法添加配置来使用他们的服务。服务提供器一旦被注册,就可被用于程序的各个地方。

类库服务提供

不是所有的类库都需要服务提供器。实际上,没有类库需要它,服务提供器的作用通常被用来启动组件并使之马上能被使用。他其实就是一个方便我们启动引导代码类库绑定到容器的工具。

延迟提供器

在每次请求中,不是所有的列在providers配置数组中的服务都会被实例化。这对在性能其实是不利的,特别是当他们已经被注册,但是项目中又没有使用到它,这就是一种浪费。比如,QueueServiceProvider服务,只有在那些利用了队列的请求中才会使用到。

为了在请求中,只实例化那些必须的服务,laravel生成了一个“服务器清单”并存储在app/storage/meta目录中。清单中列出了所有应用可能需要用到的服务,也记录了容器需要绑定的类库的名称。当应用中需要使用queue服务时,Laravel知道如何从清单中加载并实例化QueueServiceProvider。这种延迟加载服务的方式,极大的提高了整体的性能。

清单的生成

当在providers数组中添加数据时,Laravel会在下一次请求时自动重新生成清单。

有时间的话,还是要好好看看这个清单的,他对你调试延迟加载服务是非常有帮助的。

组织器

想使用Laravel构建出一个高扩展性良好的应用,那么就有必要学习并将服务提供器作为一种组织工具来管理我们的代码。当向IoC容器注入大量类时,代码都是杂乱的放到app/start文件中来操作的。我们可以使用服务提供器注册服务的方式来代替上面的方式。

万物伊始

应用所有“启动文件”都存放在app/start目录下的。在请求达到应用时,根据请求类型的不同加载相应的“引导”文件。启动文件根据当前环境在start.php之后被加载。例如:artisan.php只在终端命令行模式下被加载。

如下示例。我们的应用可能是在使用Pusher4来进行向用户的消息推送。为了将Pusher进行解耦,这里须要创建一个EventPusherInterface接口和一个PusherEventPuser实现。当需求变更时,我们就能很容易的改变消息服务商。

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...
    }
}

下面,我们创建一个EventPuserServiceProvider

use IlluminateSupportServiceProvider;

class EventPusherServiceProvider extends ServiceProvider {
    public function register()
    {
        $this->app->singleton("PusherSdk", function()
        {
            return new PusherSdk("app-key", "secret-key");
        }

        $this->app->singleton("EventPusherInterface", "PusherEventPusher");
    }
}

赞!我们对时间推送进行了清晰的抽象。同时我们还有一个不错的地方将服务注册绑定到容器中。我们只须要在app/config/app.phpprovider数组中添加EventPusherServiceProvider即可。在接下来的应用中,任何控制器和类都能使用这个注入的服务。

是否须要单例?

我们总需要合适使用bindsingleton。记住一点,一次请求只用一次用singleton,否则用bind

注意:服务提供器的$app变量来自ServiceProvider类中。他是IlluminateFoundationApplication的实例化对象,继承自Container类,所以可以上面一样调用容器中的各种方法。如果你喜欢App这种门面模式,也可以:

App::singleton("EventPusherInterface", "PusherEventPusher");

当然,服务提供器的功能不止于此,我们也可以注册云存储、数据库访问、自定义模版引擎如Twig等类型的服务。他就是你应用中的引导和管理工具,如此而已。

所以,尽情创建属于你自己的服务提供器吧。这不需要你非得发布个代码包,只是个管理管理工具,来方便应用加载各种项目须要的组件。

启动服务

当所有的服务提供器注册之后,他们就变成了“已启动”状态。每个提供器中的boot方法都会触发。我们通常会犯这样一种错误,就是在register方法试图去调用其他服务。而此时并不能保证所有的服务均已被加载,服务很可能在当前是不可用的,这就会出现错误。因此,我们应该总是在boot方法中去调用其他服务。register方法仅仅是用来将服务注册到容器中。

在boot方法中,你可以做任何事情:注册时间监听器,加载路由文件,注册过滤器,以及任何你能想到的东西。再次提示,把服务提供器作为一种组织工具来使用。也许你希望把一些监听事件组织起来?把他们放到boot方法来实现就是一个很好的方法!或者,你也可以引入一个PHP的“事件”或者“路由”文件:

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

现在我们已经学习了依赖注入和利用服务提供器来组织项目,我们有了使用Laravel创建可维护、可测试程序的应用架构的强大基础。下面,我们继续深入学习Laravel本身是如何使用服务提供器,框架如何在这个引擎下工作!

别被这些框框束缚了自己

记住,不要老想着只有程序包才能使用服务提供器。要将他作为我们组织服务的好工具。

服务核心

你应该已经注意到app配置文件中已经有很多服务了。每一个都会启动框架核心的各个部分。比如,MigrationServiceProvider负责加载数据库迁移的类库,以及加载Artisan命令;EventServiceProvider负责注册事件调度类。一些服务相对比较负责,但都是负责启动框架核心的某一部分。

约一约这些服务们

理解这些核心服务最好的方法还是去读下源码。如果能对这些服务的源码,和容器的注入非常熟悉,那么Laravel的工作原理也就会变的非常明了了。

大部分的服务都是延迟加载的,并非所有请求都会调用他们;然而框架基本的部分像FilesystemServiceProviderExceptionServiceProvider还是会随请求一起启动的。有些人会说核心服务和容器_就是_Laravel。Laravel就是将所有不同的部分组合成一个单一,内聚的整体。这些服务就是框架这栋大厦的骨架。

再啰嗦一次,想了解Laravel如何工作,还是得看源码,看看框架如何驱动这些核心服务。能明白这些服务如何组织的一块,这些服务如何实现本身的功能。深谙这些之后,也许你也能为Laravel做出自己的贡献!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22951.html

相关文章

  • Laravel深入学习7 - 框架的扩展

    摘要:组件扩展通常有两种方法向容器中绑定自己的接口实现痛过使用工厂模式实现的类注册自己的扩展。类库管理类以工厂模式实现,负责诸如缓存等驱动的实例化。闭包须要传入继承自和容器的实例化对象。当完成扩展之后要记住中替换成自己的扩展名称。 声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证9...

    yuanxin 评论0 收藏0
  • Laravel深入学习2 - 控制反转容

    摘要:控制反转容器控制反转使依赖注入变得更加便捷。有瑕疵控制反转容器是实现的控制翻转容器的一种替代方案。容器的独立使用即使没有使用框架,我们仍然可以在项目中使用安装组件来使用的控制反转容器。在没有给定任何信息的情况下,容器是无法实例化相关依赖的。 声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味...

    worldligang 评论0 收藏0
  • Laravel深入学习5 - 应用架构

    摘要:控制只是用来接收请求并请求逻辑处理类。事实上,业务逻辑无需感知网络,网络仅仅接入应用的传输机制,他不应超出应用中的路由和控制器的范畴。职责分离是编写健壮应用的关键。其他通常,类库应该以规范组织在我们的应用中。 声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另...

    lixiang 评论0 收藏0
  • 深入剖析 Laravel 服务

    摘要:划下重点,服务容器是用于管理类的依赖和执行依赖注入的工具。类的实例化及其依赖的注入,完全由服务容器自动的去完成。 本文首发于 深入剖析 Laravel 服务容器,转载请注明出处。喜欢的朋友不要吝啬你们的赞同,谢谢。 之前在 深度挖掘 Laravel 生命周期 一文中,我们有去探究 Laravel 究竟是如何接收 HTTP 请求,又是如何生成响应并最终呈现给用户的工作原理。 本章将带领大...

    abson 评论0 收藏0
  • 深入浅出 Laravel 的 Facade 外观系统

    摘要:外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。将使用者与子系统从直接耦合,转变成由外观类提供统一的接口给使用者使用,以降低客户端与子系统之间的耦合度。接下来将深入分析外观服务的加载过程。引导程序将在处理请求是完成引导启动。 本文首发于 深入浅出 Laravel 的 Facade 外观系统,转载请注明出处。 今天我们将学习 Laravel 核心架构中的另一个主题「Fac...

    KavenFan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<