최근 laravel-database-logger 패키지를 개발할 때 ServiceProvider defer
속성을 true
로 설정하면 register
메서드가 생성되는 것을 발견했습니다. 등록된 미들웨어
가 잘못되었습니다. 이 글은 Laravel Service Provider 개발 중 지연 로딩을 설정할 때 발생하는 문제에 대한 해결책을 주로 여러분과 공유합니다. 이것이 모든 사람에게 도움이 되기를 바랍니다. defer
属性设置为 true
时,会导致在 register
方法中注册的 middleware
无效。本文主要和大家分享Laravel Service Provider 开发时设置延迟加载时遇到的问题决绝办法,希望能帮助到大家。
class ServiceProvider extends \Illuminate\Support\ServiceProvider { protected $defer = true; public function register() { $this->mergeConfigFrom( __DIR__ . '/../config/config.php', 'ibrand.dblogger' ); $this->app->singleton(DbLogger::class, function ($app) { return new DbLogger(); }); //当 $defer 设置为 true 时,在路由中引用 databaselogger middleware 会报错,提示 databaselogger class not found. $this->app[\Illuminate\Routing\Router::class]->middleware('databaselogger', Middleware::class); } public function provides() { return [DbLogger::class]; } }
当问题出现的时候就怀疑是因为设置了 defer
属性设置为 true
导致的,立刻就修改源码把 protected $defer = true;
的代码注释掉,结果仍然是提示 databaselogger class not found.
,说明 Laravel 并没有注册此 ServiceProvder
接下来就是想如何解决此问题,尝试了下面的方法:
1. 验证本身代码是否存在问题
在正常注册的 AppServiceProvider
中注册自己的 ServiceProvider
public function register() { // $this->app->register(\Ibrand\DatabaseLogger\ServiceProvider::class); }
注册后结果一切正常。
2. 研究源码
在 config/app.php
中 providers
注册无效,但是在其他 ServiceProvider
中注册有效,说明是其他问题。
通过研究 IlluminateFoundationApplication
源码找到 registerConfiguredProviders
方法:
Laravel 是在此方法中去读取 config/app.php
中的 providers
内容并load
到 ProviderRepository
中。
(new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath())) ->load($providers->collapse()->toArray());
重点在 $this->getCachedServicesPath()
,通过源码发现 Laravel 是根据 bootstrap/cache/services.php
文件去决定如何注册 ServiceProvider
。
此时想到了为什么之前注释了 //protected $defer = true;
代码后仍然无效的原因。
所以为了让注释后的 //protected $defer = true;
代码有效需要执行
php artisan clear-compiled php artisan optimize
之后问题就解决了,也更加深入理解了 ServiceProvider 的原理。
所以切记:如果准备采用延迟加载ServiceProvider
时,严禁进行注册 middleware, route 等系列操作。同时,更改defer
属性值后,需要执行php artisan clear-compiled
和php artisan optimize
以更新 ServiceProvider 缓存。
3. 为什么 AppServiceProvider 中注册有效?
愿意很简单,因为 AppServiceProvider
并没有延迟加载,因此在执行 AppServiceProvider
中 register
方法去注册新的 ServiceProvider
也是不会延迟加载的。
谨慎使用延迟加载 ServiceProvider
更改 defer
属性值后,需要执行 php artisan clear-compiled
和 php artisan optimize
以更新 ServiceProvider 缓存。
严禁在延迟加载的 ServiceProvider
注册 middleware
和 route
rrreee
defer
속성을 true
로 설정하여 발생한 문제인 것으로 의심되어 즉시 소스 코드를 수정하여 protected $defer를 설정했습니다. = true;
코드가 주석 처리되어도 결과는 여전히 databaselogger 클래스를 찾을 수 없습니다.
라는 메시지입니다. 이는 Laravel이 이 ServiceProvder
1. 자신의 코드에 문제가 있는지 확인하세요.
에 자신의 ServiceProvider
를 등록하세요. AppServiceProvider
가 정상적으로 등록되었습니다. rrreee등록 후 모든 것이 잘 진행되었습니다.
2. 소스 코드 연구 config/app.php
의 providers
등록은 유효하지 않지만 다른 ServiceProvider에서는
등록이 유효하다면 다른 문제가 있다는 뜻입니다.
IlluminateFoundationApplication
소스 코드를 연구하여 registerConfiguredProviders
메서드를 찾으세요. Laravel은 이 메서드 코드>공급자에서 config/app.php
를 읽습니다. 콘텐츠를 ProviderRepository
에 로드
합니다. rrreee
$this->getCachedServicesPath()
에 있습니다. 소스 코드를 통해 Laravel은 bootstrap/cache를 기반으로 <code>ServiceProvider를 등록하는 방법을 결정한다는 것을 확인했습니다. /services.php
파일입니다.
이때, 앞서 댓글을 달았던 //protected $defer = true;
코드가 여전히 유효하지 않은 이유를 생각해봤습니다.
//protected $defer = true;
코드를 유효하게 만들기 위해서는 실행이 필요합니다🎜rrreee🎜이후에는 문제가 해결되었고 ServiceProvider의 원칙이 더욱 강화되었습니다. 깊이 이해했습니다. 🎜그러므로 기억하세요: 지연 로딩🎜3. AppServiceProvider에 등록하는 것이 유효한 이유는 무엇입니까? 🎜🎜매우 간단합니다.ServiceProvider
를 사용하려는 경우 미들웨어, 경로 및 기타 일련의 작업을 등록하는 것은 엄격히 금지됩니다. 동시에defer
속성 값을 변경한 후php artisanclear-compiled
및php artisan Optimize
를 실행하여 ServiceProvider를 업데이트해야 합니다. 은닉처.
AppServiceProvider
는 로딩을 지연시키지 않기 때문에 AppServiceProvider
의 register
메소드를 실행하여 새로운 ServiceProvider도 지연 로드되지 않습니다. 🎜ServiceProvider
🎜🎜defer 속성 값 뒤에 <code>php artisanclear-compiled
및 php artisan Optimize
를 실행하여 ServiceProvider 캐시를 업데이트해야 합니다. 🎜🎜ServiceProvider
에 미들웨어
및 route
를 등록하는 것은 엄격히 금지됩니다. 🎜🎜🎜🎜관련 권장 사항: 🎜🎜🎜🎜laravel5의 서비스 공급자 및 Facade 생성 방법에 대한 자세한 설명🎜🎜🎜🎜Laravel Service Providers 문제🎜🎜🎜🎜laravel5가 서비스 공급자 및 Facade를 생성하는 방법🎜🎜🎜🎜 🎜위 내용은 Laravel Service Provider 개발 중 지연 로딩을 설정할 때 발생하는 문제에 대한 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!