源码解读:Laravel php artisan route:cache

学 Laravel 和 Vuejs 你真应该来 codecasts.com !php

Laravel ​route:cache 能够直接缓存路由文件,这样其实能够在必定程度上提升 Laravel 应用的性能,由于缓存路由以后,在访问应用的时候咱们就不用再次去计算路由的消耗了,能够直接根据缓存文件来进行匹配处理。laravel

然而,本文的讨论重点,仍是 route:cache 背后的源码,是怎么作到这一步的。bootstrap

从哪开始看

route:cache 源码位于 Illuminate\Foundation\Console\RouteCacheCommand缓存

你仍是可使用编辑器搜 RouteCacheCommand,就能够看到源码了。
主要的代码逻辑就在 fire() 方法里面:app

public function fire()
    {
        $this->call('route:clear');
        //.... other codes
    }

第一步

执行 $this->call('route:clear'),这部分的逻辑是:若是以前有缓存过路由文件,那么先清除旧的路由缓存,这个部分的代码位于 Illuminate\Foundation\Console\RouteClearCommand 中,仍是看到 fire() 方法这里:编辑器

public function fire()
    {
        $this->files->delete($this->laravel->getCachedRoutesPath());

        $this->info('Route cache cleared!');
    }

主要就是执行删除动做,将以前的缓存路由删除;这个源码就在 Illuminate\Foundation\ApplicationgetCachedRoutesPath() 中:性能

public function getCachedRoutesPath()
    {
        return $this->bootstrapPath().'/cache/routes.php';
    }

因此这样一看,就是删除了 bootstrap/cache/routes.php 这个文件,那么这个文件其实就是 Laravel 的路由缓存文件,以后会从新生成这个 routes.php 文件。ui

第二步

获取全部的路由和其对应关系,在 RouteCacheCommandfire() 方法往下:this

public function fire()
    {
      //... codes
      $routes = $this->getFreshApplicationRoutes();
      //... codes
    }

其中的 getFreshApplicationRoutes() 的代码是:code

protected function getFreshApplicationRoutes()
    {
        return tap($this->getFreshApplication()['router']->getRoutes(), function ($routes) {
            $routes->refreshNameLookups();
            $routes->refreshActionLookups();
        });
    }

这里又包含一个新的方法 getFreshApplication() ,这个方法也是位于一样的文件中:

protected function getFreshApplication()
    {
        return tap(require $this->laravel->bootstrapPath().'/app.php', function ($app) {
            $app->make(ConsoleKernelContract::class)->bootstrap();
        });
    }

这样一看,总结这两个方法作的事情就是:

getFreshApplication() 获取一个 Laravel 的核心实例, 而后上面的 getFreshApplicationRoutes() 中的 $this->getFreshApplication()['router']->getRoutes() 就能够理解了,也就是至关于 app('router')->getRoutes(),这个 getRoutes() 就是负责获取全部路由,这部分的源码位于 Illuminate\Routing\RoutergetRoutes() 中。

第三步

序列化全部路由注册映射关系,仍是在 RouteCacheCommandfire() 方法中:

public function fire()
{
   foreach ($routes as $route) {
        $route->prepareForSerialization();
    }
}

上面的 prepareForSerialization() 方法位于 Illuminate\Routing\Route 中的 prepareForSerialization() 中。

第四步

序列化完成以后,将内容写入文件中,这个文件正是一开始删除的 bootstrap/cache/routes.php,来看代码 RouteCacheCommandfire() 方法:

$this->files->put(
    $this->laravel->getCachedRoutesPath(), 
    $this->buildRouteCacheFile($routes)
 );

其中的 $this->laravel->getCachedRoutesPath() 在文章一开始就说明了,它是找到了 bootstrap/cache/routes.php 这个文件,而后写入的内容就是:

protected function buildRouteCacheFile(RouteCollection $routes)
    {
        $stub = $this->files->get(__DIR__.'/stubs/routes.stub');

        return str_replace('{{routes}}', base64_encode(serialize($routes)), $stub);
    }

在这个方法中,看到 base64_encode(serialize($routes)) 这行代码,因此你会在缓存的 routes.php 中看到相似下面的代码:

app('router')->setRoutes(
    unserialize(base64_decode('TzozNDoiSWxsdW1pbm...'))
);

一堆 base64 的字符串,这些字符串 base64_decode() 出来大概是这样的:

这里就是完整的注册路由啦!

而后在下次访问 Laravel 项目的时候,就是能够直接从缓存的 routes 文件读取路由了。因此到这里,route:cache 的源码解读就完成了。

Happy Hacking

相关文章
相关标签/搜索