在自定義 Service Provider 的 register() 中調用 Auth::extend() 拋出 Call to undefined method Illuminate\Support\Facades\Auth::extend()。根因是 AuthServiceProvider 設置了 \$defer = true,導致 Auth 服務延遲加載,當自定義 Provider 運行時 Auth 尚未註冊。
// LoauthServiceProvider.php
public function register() {
Auth::extend('loauth', function ($app) { ... }); // 報錯:方法不存在
}
Laravel 啟動流程 (Illuminate\Foundation\ProviderRepository::load):
register()。$app->setDeferredServices($manifest['deferred']) 標記延遲服務。register()。自定義 Provider 若在 config/app.php 中排在 AuthProvider 之前,且自身非延遲,則執行 register() 時 Auth 尚未註冊,Facade 代理的底層實例不存在,故報錯。
public function register() {
// 強制實例化並註冊 Auth 服務
$authProvider = new \Illuminate\Auth\AuthServiceProvider($this->app);
$authProvider->register();
// 現在可以安全調用
Auth::extend('loauth', function ($app) { ... });
}
| 方案 | 優點 | 缺點 |
|---|---|---|
| 手動 new Provider->register() | 零配置修改,精確控制 | 依賴內部類名,升級風險極低 |
| 將自定義 Provider 設為 \$defer=true | 順應框架設計 | 需實現 provides(),且仍需確保加載順序 |
| 在 AppServiceProvider::boot() 中調用 | 所有 Provider 已註冊完成 | boot 階段較晚,可能影響其他早期邏輯 |
App\Providers\AuthServiceProvider 自身的 boot() 中完成(Laravel 5.2+ 已內置 Auth::viaRequest() 等擴展點)。composer.json extra.laravel.providers 聲明依賴順序。\$defer 機制:即時 Provider 不能在 register() 中依賴延遲服務。深入理解容器啟動順序,是開發高質量 Laravel 擴展包的關鍵。