From a22e4538ab705a7b7d23c8b65365b97e0b704082 Mon Sep 17 00:00:00 2001 From: FreeScout Date: Tue, 13 Nov 2018 22:27:07 -0800 Subject: [PATCH] Override Laravel ProviderRepository.php to catch provider not found errors on updating --- config/app.php | 7 +-- .../Foundation/ProviderRepository.php | 46 ++++++++++++++++--- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/config/app.php b/config/app.php index ddca6146..a57d2532 100644 --- a/config/app.php +++ b/config/app.php @@ -263,11 +263,8 @@ return [ /* * Custom Service Providers... */ - // We need to be careful when deleting service providers - // as Laravel config is cached with `config:cache`. - // If we remove some service provider file from here and from disk, - // when updating the app, users will receive "Class '...' not found" error, - // because their cached config still has this service provider listed. + // We can freely add or remove providers from this file. + // Updating will work without problems. // Autodiscovery did not work for this one, becasuse it's composer.json // does not have a `extra` section. diff --git a/overrides/Illuminate/Foundation/ProviderRepository.php b/overrides/Illuminate/Foundation/ProviderRepository.php index 7d4b1d89..4caa39e9 100644 --- a/overrides/Illuminate/Foundation/ProviderRepository.php +++ b/overrides/Illuminate/Foundation/ProviderRepository.php @@ -29,6 +29,12 @@ class ProviderRepository */ protected $manifestPath; + /** + * Non-cached config. + * @var [type] + */ + protected $appConfig = []; + /** * Create a new service repository instance. * @@ -71,8 +77,37 @@ class ProviderRepository // We will go ahead and register all of the eagerly loaded providers with the // application so their services can be registered with the application as // a provided service. Then we will set the deferred service list on it. - foreach ($manifest['eager'] as $provider) { - $this->app->register($provider); + foreach ($manifest['eager'] as $i => $provider) { + // Application config is cached with `config:cache`. + // If we remove some service provider file from app.php and from disk, + // when updating the app, users will receive "Class '...' not found" error, + // because their cached config still has this service provider listed. + try { + $this->app->register($provider); + } catch (\Throwable $e) { + + preg_match("/Class '([^']+)' not found/", $e->getMessage(), $matches); + + if (empty($matches[1])) { + throw $e; + } + $provider_name = $matches[1]; + // Read app.php and check if service provider is listed there, + // if not listed, we can ignore the exception. + if (!$this->appConfig) { + $this->appConfig = include base_path().DIRECTORY_SEPARATOR.'config/app.php'; + } + + if (!in_array($provider_name, $this->appConfig['providers'])) { + // Just log the error + // After cache will be cleared, problem will go away + \Log::error($e->getMessage()); + unset($manifest['eager'][$i]); + continue; + } else { + throw $e; + } + } } $this->app->addDeferredServices($manifest['deferred']); @@ -140,7 +175,6 @@ class ProviderRepository // and determine if the manifest should be recompiled or is current. $manifest = $this->freshManifest($providers); - $app_config = []; foreach ($providers as $i => $provider) { // Application config is cached with `config:cache`. // If we remove some service provider file from app.php and from disk, @@ -158,11 +192,11 @@ class ProviderRepository $provider_name = $matches[1]; // Read app.php and check if service provider is listed there, // if not listed, we can ignore the exception. - if (!$app_config) { - $app_config = include base_path().DIRECTORY_SEPARATOR.'config/app.php'; + if (!$this->appConfig) { + $this->appConfig = include base_path().DIRECTORY_SEPARATOR.'config/app.php'; } - if (!in_array($provider_name, $app_config['providers'])) { + if (!in_array($provider_name, $this->appConfig['providers'])) { // Just log the error // After cache will be cleared, problem will go away \Log::error($e->getMessage());