>  기사  >  백엔드 개발  >  Laravel Service Provider 개발 중 지연 로딩을 설정할 때 발생하는 문제에 대한 솔루션

Laravel Service Provider 개발 중 지연 로딩을 설정할 때 발생하는 문제에 대한 솔루션

小云云
小云云원래의
2018-01-03 15:05:431875검색

최근 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.phpproviders 注册无效,但是在其他 ServiceProvider 中注册有效,说明是其他问题。

通过研究 IlluminateFoundationApplication 源码找到 registerConfiguredProviders 方法:

Laravel 是在此方法中去读取 config/app.php 中的 providers 内容并loadProviderRepository 中。

(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 并没有延迟加载,因此在执行 AppServiceProviderregister 方法去注册新的 ServiceProvider 也是不会延迟加载的。

总结

  1. 谨慎使用延迟加载 ServiceProvider

  2. 更改 defer 属性值后,需要执行 php artisan clear-compiled php artisan optimize 以更新 ServiceProvider 缓存。

  3. 严禁在延迟加载的 ServiceProvider 注册 middlewarerouterrreee

    문제가 발생했을 때 defer 속성을 ​​true로 설정하여 발생한 문제인 것으로 의심되어 즉시 소스 코드를 수정하여 protected $defer를 설정했습니다. = true; 코드가 주석 처리되어도 결과는 여전히 databaselogger 클래스를 찾을 수 없습니다.라는 메시지입니다. 이는 Laravel이 이 ServiceProvder
를 등록하지 않았음을 나타냅니다. 다음 단계는 이 문제를 해결하는 방법입니다. 다음 방법을 시도해 보세요.


1. 자신의 코드에 문제가 있는지 확인하세요.

에 자신의 ServiceProvider를 등록하세요. AppServiceProvider가 정상적으로 등록되었습니다. rrreee등록 후 모든 것이 잘 진행되었습니다.

2. 소스 코드 연구 config/app.phpproviders 등록은 유효하지 않지만 다른 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의 원칙이 더욱 강화되었습니다. 깊이 이해했습니다. 🎜
그러므로 기억하세요: 지연 로딩 ServiceProvider를 사용하려는 경우 미들웨어, 경로 및 기타 일련의 작업을 등록하는 것은 엄격히 금지됩니다. 동시에 defer 속성 값을 변경한 후 php artisanclear-compiledphp artisan Optimize를 실행하여 ServiceProvider를 업데이트해야 합니다. 은닉처.
🎜3. AppServiceProvider에 등록하는 것이 유효한 이유는 무엇입니까? 🎜🎜매우 간단합니다. AppServiceProvider는 로딩을 지연시키지 않기 때문에 AppServiceProviderregister 메소드를 실행하여 새로운 ServiceProvider도 지연 로드되지 않습니다. 🎜

요약

  1. 🎜지연 로딩을 주의해서 사용하세요 ServiceProvider🎜🎜
  2. 🎜변경 defer 속성 값 뒤에 <code>php artisanclear-compiledphp artisan Optimize를 실행하여 ServiceProvider 캐시를 업데이트해야 합니다. 🎜🎜
  3. 🎜지연 로드된 ServiceProvider미들웨어route를 등록하는 것은 엄격히 금지됩니다. 🎜🎜🎜🎜관련 권장 사항: 🎜🎜🎜🎜laravel5의 서비스 공급자 및 Facade 생성 방법에 대한 자세한 설명🎜🎜🎜🎜Laravel Service Providers 문제🎜🎜🎜🎜laravel5가 서비스 공급자 및 Facade를 생성하는 방법🎜🎜🎜🎜 🎜

위 내용은 Laravel Service Provider 개발 중 지연 로딩을 설정할 때 발생하는 문제에 대한 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.