Yii2:如何捕获引导模块抛出的异常?
Alright, let's break this down. You're trying to catch exceptions like unreachable URLs or invalid JSON in your custom DataProvider bootstrap component, and you're unsure where to hook this up even with a custom ErrorHandler already in place. Here's how to approach this properly:
1. Catch Exceptions Directly in Your Bootstrap Class (Recommended)
Since the errors originate from your DataProvider's logic, the cleanest approach is to handle them inside the bootstrap class itself. This lets you target specific error scenarios and still pass relevant exceptions to your custom ErrorHandler for user-facing handling.
First, make sure your DataProvider implements the BootstrapInterface (required for Yii2 bootstrap components). Then wrap your API fetch/JSON parsing logic in a try-catch block:
namespace app\components; use yii\base\BootstrapInterface; use yii\web\ServerErrorHttpException; use yii\helpers\Json; use yii\httpclient\Client; use GuzzleHttp\Exception\ConnectException; use yii\base\InvalidJsonException; class DataProvider implements BootstrapInterface { public $campaignJsonUrl; public function bootstrap($app) { try { // Fetch the JSON data using Yii's HTTP Client (more robust than file_get_contents) $client = new Client(); $response = $client->get($this->campaignJsonUrl)->send(); // Check if the request was successful if (!$response->isOk) { throw new ServerErrorHttpException( "Failed to fetch campaign data: HTTP {$response->statusCode}", $response->statusCode ); } // Parse JSON and validate it $data = Json::decode($response->content); if ($data === null) { throw new ServerErrorHttpException("Invalid JSON returned from campaign API"); } // Store the parsed data for later use (e.g., as an app component) $app->set('campaignData', $data); } catch (ConnectException $e) { // Handle unreachable URL errors \Yii::error("Campaign API URL unreachable: {$e->getMessage()}", __METHOD__); // Re-throw a Yii-compatible exception for your ErrorHandler to catch throw new ServerErrorHttpException("Cannot connect to campaign data source", 0, $e); } catch (InvalidJsonException $e) { // Handle invalid JSON errors \Yii::error("Invalid JSON from campaign API: {$e->getMessage()}", __METHOD__); throw new ServerErrorHttpException("Invalid campaign data format", 0, $e); } catch (\Exception $e) { // Catch-all for unexpected errors \Yii::error("Unexpected error loading campaign data: {$e->getMessage()}", __METHOD__); throw new ServerErrorHttpException("Failed to load campaign data", 0, $e); } } }
2. Ensure Your Custom ErrorHandler Catches the Exceptions
Your existing ErrorHandler should automatically catch these re-thrown exceptions, but make sure it's properly configured in your config/web.php:
'components' => [ 'errorHandler' => [ 'class' => 'app\components\ErrorHandler', 'errorAction' => 'site/error', // Verify this action exists in your SiteController ], // ... other components ],
If you want to add custom logic for these specific campaign-related errors, override the handleException method in your ErrorHandler:
namespace app\components; use yii\web\ErrorHandler as BaseErrorHandler; use yii\web\ServerErrorHttpException; class ErrorHandler extends BaseErrorHandler { protected function handleException($exception) { // Add custom handling for campaign data errors if ($exception instanceof ServerErrorHttpException && str_contains($exception->getMessage(), 'campaign')) { \Yii::error( "Campaign Data Error: {$exception->getMessage()} | Previous: {$exception->getPrevious()?->getMessage()}", __METHOD__ ); // You could also redirect to a specific error page or return a custom response here } // Let the parent class handle the rest of the exception logic parent::handleException($exception); } }
3. Fallback: Global Exception Catch in Entry Script
If you prefer to catch all bootstrap-stage exceptions at the highest level, you can wrap your application initialization in a try-catch block in your web/index.php entry script:
<?php defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php'; $config = require __DIR__ . '/../config/web.php'; try { $app = new yii\web\Application($config); $app->run(); } catch (\Exception $e) { // Initialize your custom ErrorHandler and pass the exception $errorHandler = new app\components\ErrorHandler(); $errorHandler->handleException($e); }
This will catch any exceptions that slip through the bootstrap class, but it's less targeted than handling errors directly in DataProvider.
内容的提问来源于stack exchange,提问作者NaturalBornCamper

