因爲 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, ... ], ... ];