资讯专栏INFORMATION COLUMN

Laravel 配置项即时载入的服务提供者

liukai90 / 3256人阅读

摘要:配置项即时载入的服务提供者根目录所有即时载入的服务注册完成之后,会立即调用方法,并标记为已载入。最终就是将数组设置给的属性将运用到所有的路由,再加载。

Laravel 配置项即时载入的服务提供者 (根目录:/var/www/laravel/)
所有即时载入的服务注册完成之后,会立即调用 register 方法,并标记为已载入。
随后通过 IlluminateFoundationBootstrapBootProviders 启动项来调用所有的即时加载服务提供者的 boot 方法

查看根据 config/app.php 中的 providers 生成的 bootstrap/cache/services.php
"eager" => 
  array (
    // 系统服务提供者
    0 => "IlluminateAuthAuthServiceProvider",                       // 注入验证相关对象
    1 => "IlluminateCookieCookieServiceProvider",                   // 注入cookie对象
    2 => "IlluminateDatabaseDatabaseServiceProvider",               // 注入db相关对象
    3 => "IlluminateEncryptionEncryptionServiceProvider",           // 注入加解密对象
    4 => "IlluminateFilesystemFilesystemServiceProvider",           // 注入文件相关对象
    5 => "IlluminateFoundationProvidersFoundationServiceProvider",// 注入基础的请求对象
    6 => "IlluminateNotificationsNotificationServiceProvider",      // 注入通知对象
    7 => "IlluminatePaginationPaginationServiceProvider",           // 注入分页相关对象
    8 => "IlluminateSessionSessionServiceProvider",                 // 注入session相关对象
    9 => "IlluminateViewViewServiceProvider",                       // 注入视图相关对象
    10 => "LaravelPassportPassportServiceProvider",                 // 注入passport相关对象
    
    // 配置项服务提供者
    11 => "AppProvidersAppServiceProvider",
    12 => "AppProvidersAuthServiceProvider",
    13 => "AppProvidersEventServiceProvider",
    14 => "AppProvidersRouteServiceProvider",
  )
路由相关服务提供者
// 主要是注册完之后的 boot 方法调用
AppProvidersRouteServiceProvider
public function boot()
{
    // 可以加入自己的操作
    parent::boot();
}
public function boot()
{
    $this->setRootControllerNamespace();
    // 若执行了 php artisan routes:cache(自动生成路由缓存文件,注意:建议只在项目上线时操作),直接加载 
    if ($this->app->routesAreCached()) {
        $this->loadCachedRoutes();
    } else {
        // 加载路由
        $this->loadRoutes();
        // 设置系统启动时的事件监听函数
        $this->app->booted(function () {
            $this->app["router"]->getRoutes()->refreshNameLookups();
        });
    }
}
protected function setRootControllerNamespace()
{
    if (! is_null($this->namespace)) {
        // 设置 $this->instances["url"] (IlluminateRoutingUrlGenerator对象)的 rootNamespace 属性
        $this->app[UrlGenerator::class]->setRootControllerNamespace($this->namespace);
    }
}
public function routesAreCached()
{
    return $this["files"]->exists($this->getCachedRoutesPath());
}
public function getCachedRoutesPath()
{
    return $this->bootstrapPath()."/cache/routes.php";
}
protected function loadRoutes()
{
    if (method_exists($this, "map")) {
        $this->app->call([$this, "map"]);
    }
}
public function map()
{
    $this->mapApiRoutes();
    $this->mapWebRoutes();
}
// API 相关的路由
protected function mapApiRoutes()
{
    Route::prefix("api")
         ->middleware("api")
         ->namespace($this->namespace)
         ->group(base_path("routes/api.php"));
}
// WEB 相关的路由
protected function mapWebRoutes()
{
    Route::middleware("web")
         ->namespace($this->namespace)
         ->group(base_path("routes/web.php"));
}
public function booted($callback)
{
    $this->bootedCallbacks[] = $callback;
    // 如果应用已经启动了,则直接调用
    if ($this->isBooted()) {
        $this->fireAppCallbacks([$callback]);
    }
}

// Route 是 Facde 的调用方式
分析: Route::middleware("web")
        ->namespace($this->namespace)
        ->group(base_path("routes/web.php"));

Route::middleware
public static function __callStatic($method, $args)
{
    // 获取应用的 router 对象
    $instance = static::getFacadeRoot();

    if (! $instance) {
        throw new RuntimeException("A facade root has not been set.");
    }
    // 将 Router::middleware() 转化为应用的 Router->middleware() 方式,若 Router 没有 middleware 方法,则直接触发 __call
    return $instance->$method(...$args);
}
public function __call($method, $parameters)
{
    if (static::hasMacro($method)) {
        return $this->macroCall($method, $parameters);
    }
    // 将不存在的方法的调用委托给 RouteRegistrar 处理,
    return (new RouteRegistrar($this))->attribute($method, $parameters[0]);
}
public function attribute($key, $value)
{
    // 只允许指定的属性设置($allowedAttributes = ["as", "domain", "middleware", "name", "namespace", "prefix",])
    if (! in_array($key, $this->allowedAttributes)) {
        throw new InvalidArgumentException("Attribute [{$key}] does not exist.");
    }
    // 支持.方式来存放属性
    $this->attributes[array_get($this->aliases, $key, $key)] = $value;

    return $this;
}
public function group($callback)
{
    $this->router->group($this->attributes, $callback);
}
public function group(array $attributes, $routes)
{
    $this->updateGroupStack($attributes);
    $this->loadRoutes($routes);
    array_pop($this->groupStack);
}
protected function loadRoutes($routes)
{
    if ($routes instanceof Closure) {
        $routes($this);
    } else {
        $router = $this;
        require $routes;
    }
}

小结

Route::middleware("web")
        ->namespace($this->namespace)
        ->group(base_path("routes/web.php"));
        
实际就是将 middleware namespace 加入到 RouteRegistrar 对象里面的 attributes 数组属性,并返回
RouteRegistrar 对象,再调用 RouteRegistrar 对象的 group 方法,也就是调用 router 对象的 group
方法。最终就是将["middleware" => "web", "namespace" => $this->namespace] 数组设置给 
$this->router 的groupStack 属性(将运用到所有的路由),再加载 config/web.php。

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

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

相关文章

  • 记一次 Laravel 应用性能调优经历

    摘要:为了一探究竟,于是开启了这次应用性能调优之旅。使用即时编译器和都能轻轻松松的让你的应用程序在不用做任何修改的情况下,直接提高或者更高的性能。 这是一份事后的总结。在经历了调优过程踩的很多坑之后,我们最终完善并实施了初步的性能测试方案,通过真实的测试数据归纳出了 Laravel 开发过程中的一些实践技巧。 0x00 源起 最近有同事反馈 Laravel 写的应用程序响应有点慢、20几个并...

    warkiz 评论0 收藏0
  • Laravel Kernel引导流程分析

    摘要:实例化各服务提供者,根据其属性将服务进行分类延迟服务即时服务,从而得到一个数组格式如,延迟处理注册延迟的服务,以后再进行调用注册延迟的事件即时处理直接进行注册调用等,并重新写入到,然后根据此文件进行相应的处理。 Laravel Kernel引导流程分析 代码展示 protected function sendRequestThroughRouter($request) { # ...

    yagami 评论0 收藏0
  • Lumen配置文件按需加载出现

    摘要:问题分析通过阅读源码发现,中的服务都是按需绑定并加载。在服务按需绑定并加载的时候,使用了类似组件的形式通过载入配置项并绑定服务。因为在这个时候的相关配置文件还没有被载入。 问题描述 公司一个高并发API需要从Laravel移植到Lumen,由于数据库配置信息是通过远程或者缓存读取后动态配置,所以在中间件时使用到了 Config::set 然而实际运行时发现数据库配置并没有更新。 由于是...

    lentoo 评论0 收藏0
  • Laravel 5 程序优化技巧

    摘要:使用即时编译器和都能轻轻松松的让你的应用程序在不用做任何修改的情况下,直接提高或者更高的性能,之前做个一个实验,具体请见使用提升程序性能。 本文经授权转自 PHPHub 社区 说明 性能一直是 Laravel 框架为人诟病的一个点,所以调优 Laravel 程序算是一个必学的技能。 接下来分享一些开发的最佳实践,还有调优技巧,大家有别的建议也欢迎留言讨论。 这里是简单的列表: 配置信...

    habren 评论0 收藏0
  • Laravel 广播系统工作原理

    摘要:今天,让我们深入研究下的广播系统。广播系统的目的是用于实现当服务端完成某种特定功能后向客户端推送消息的功能。这种使用场景可以完美诠释广播系统的工作原理。另外,本教程将使用广播系统实现这样一个即时通信应用。 这是一篇译文,译文首发于 Laravel 广播系统工作原理,转载请注明出处。 今天,让我们深入研究下 Laravel 的广播系统。广播系统的目的是用于实现当服务端完成某种特定功能后向...

    alphahans 评论0 收藏0

发表评论

0条评论

liukai90

|高级讲师

TA的文章

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