因为 FileStore 在存储不过时的key的expire时使用了 9999999999
, 致使最后在使用 Carbon 处理时日期溢出, 所以本身修改了一下, 新增一个 App\Extensions\Cache\FileStore
文件php
<?php namespace App\Extensions\Cache; class FileStore extends \Illuminate\Cache\FileStore { protected function expiration($seconds) { $expiration = parent::expiration($seconds); return $expiration === 9999999999 ? 2147483600 : $expiration; } }
并在 App\Providers\AppServiceProvider::boot()
中扩展该缓存驱动laravel
Cache::extend('file2', function ($app, $config) { return Cache::repository(new FileStore($app['files'], $config['path'])); });
最后修改了默认的缓存驱动 config/cache.php
json
return [ 'default' => 'file2', 'stores' => [ ... 'file' => [ 'driver' => 'file2', ... ], ... ] ];
这时候问题出来了, 不管是启动 php artisan tinker
或网页直接访问, 都会报错:bootstrap
Driver [file2] is not supported
extra.laravel.providers: ["Laravel\\Telescope\\TelescopeServiceProvider"]
数组
composer 在安装/更新包时, 会将全部安装的包的信息存储在 vendor/composer/installed.json
, 其中包含每一个包的安装信息及其配置的composer.json文件缓存
项目 composer.json 根据其配置 `scripts.post-autoload-dump
在 autoload-dump
后会执行 php artisan package:discover --ansi
命令app
上述命令对应的是 Illuminate\Foundation\Console\PackageDiscoverCommand
文件.composer
它会调用 Illuminate\Foundation\PackageManifest::build()
, 该方法会将 vendor/composer/installed.json
中配置了 extra.laravel.providers
的项提取出来, 并保存在 bootstrap/cache/packages.php
中.ide
这部分解析能够参考: https://divinglaravel.com/lar...
在laravel启动过程当中, Illuminate\Foundation\Application::registerConfiguredProviders()
会逐个注册所需的服务提供者, 服务提供者列表来源包括: config('app.providers')
以及 laravel 包自动发现策略.post
public function registerConfiguredProviders() { $providers = Collection::make($this->config['app.providers']) ->partition(function ($provider) { return Str::startsWith($provider, 'Illuminate\\'); }); $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]); (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath())) ->load($providers->collapse()->toArray()); }
上述代码分析:
第3行: 将配置中 app.providers
中的服务提供者根据字符串前缀匹配分开, 此时 $providers
值大体是这样的:
{ 0 : [ "Illuminate\....." ... "Illuminate\....." ], 1 : [ "App\Providers\AppServiceProvider::class", ... "App\Providers\RouteServiceProvider::class", ], }
第8行: 将laravel包自动发现策略获取的服务提供者列表插入到 $providers
数组中 1
的位置, 原先的 1
挪到 2
, 此时 $providers
数组大体以下:
{ 0 : [ "Illuminate\....." ... "Illuminate\....." ], 1 : [ ... "Laravel\Telescope\TelescopeServiceProvider", ... ], 2 : [ "App\Providers\AppServiceProvider", ... "App\Providers\RouteServiceProvider", ], }
第10行: 将 $providers
数组扁平化, 顺序则是依次 0, 1, 2 这样分别 register(注册) 这些服务提供者.
在laravel启动初始化的最后还会依次按 register(注册) 的顺序依次 boot(启动)上述注册的服务提供者.
对于 Laravel\Telescope\TelescopeServiceProvider
这个服务提供者, 按照以下的调用顺序
Laravel\Telescope\TelescopeServiceProvider::boot() | V Laravel\Telescope\Telescope::start() | V Laravel\TelescopeRegistersWatchers::registerWatchers() | V Laravel\Telescope\Watchers\DumpWatcher::register() ↑ 这里的代码调用 $this->cache->get("...")
在 Laravel\Telescope\Watchers\DumpWatcher::register()
其中的代码调用了缓存相关接口, 然而此时根本就没有执行到 App\Providers\AppServiceProvider::boot()
, 天然会致使报错没法找到该缓存驱动.
基本思路就是调整 Laravel\Telescope\TelescopeServiceProvider
服务提供者的加载顺序, 使其在 App\Providers\AppServiceProvider
以后加载.
这里给出一个方案:
配置项目的 composer.json
, 使laravel的包自动发现策略忽略 TelescopeServiceProvider
{ ... "extra": { "laravel": { "dont-discover": [ "laravel/telescope" ] } }, ... }
将 TelescopeServiceProvider
手动加入到服务提供者列表中, 注意顺序
修改 config/app.php
return [ ... 'providers' => [ ... App\Providers\AppServiceProvider::class, ... Laravel\Telescope\TelescopeServiceProvider::class, App\Providers\TelescopeServiceProvider::class, ... ], ... ];