try/catch doesn't intercept all errors

Hi guys,

I just have noticed,that yii doesn’t intercept all errors using Exception class yii\base\Exception.

Following code will throw out error like this:




Error

Class 'frontend\modules\kontakt\controllers\Ekontak' not found



That’s no tragedy,'cause it’s to me to avoid error like this. Nevermind, I’m confused about this,'cause I thought, base exception class will intercept really all errors.

Any ideas,what is wrong with this code?




public function actionCreate($id) {

try {

$model = new KontaktAdresse();

$model_ekontakt = new EKontak();//this error won't be intercepted!Why?

.

.   

}catch (yii\base\Exception $error) {

	$go_back = "/kontakt/kontakt-adresse/index";

	$pk = KontaktAdresse::findOne($id);

	try {

		$id = EKontakt::find()->

		leftJoin('kontakt_adresse', 'kontakt_adresse.id_e_kontakt = e_kontakt.id')->

		where(['kontakt_adresse.id_e_kontakt' => $model::findOne([$pk])->id_e_kontakt])->one()->id_person; 

		\common\wsl_components\error_handling::error($error, $go_back, $id);

 	}catch (yii\base\Exception $error) {

		$go_back = "/bewerber/bewerber/index";

		\common\wsl_components\error_handling::error_without_id($error, $go_back);

	}//End of second catch

}//End of first catch

}//End of method




Using


  } catch (\yii\base\UnknownClassException $error) {

instead won’t intercept error,too?

How can this be?

Yii does intercept all errors.

Where did you get the error information stated above? I’m sure you saw it in your web browser, not only the error summary you quoted but also with a detailed call stack information. Who took care to display it? It was Yii, of course.

The reason why your try-catch block didn’t work is because the line “$model_ekontakt = new EKontak();” invoked an internal method of Yii in which another try-catch block is used. A classNotFoundException was caught in this internal block and was handed over to the error handler immediately without returning back to your code.

And another thing to note is that Yii behaves differently in error handling depending on whether ‘YII_DEBUG’ is defined or not.

In debug mode, Yii will use the internal error action/view for those fatal errors that should be treated only by the developer. With detailed error information including call stack, it will help the developer to debug errors.

But in production mode, Yii will use the user defined error action/view for them, but without detailed information this time. “Sorry, an internal server error has occurred. Please contact the developer.” or something like that. This is because we don’t want to bother our users with technical jargon in which they have no interest. And it is also because we don’t want to show the sensitive information of the system to the possible hackers. (For debugging purpose, you can check the logs.)

So, as long I am in development modus, fatal exceptions like above will be shown in browser, but in release modus,error will be intercepted using my error class.

Is this conclusion of ur explanations correct?

Yes.

No. It will still be handled by the internal try-catch block of yii core code. Usually it will not get back to your try-catch block, although the user defined error action (usually ‘site/error’) may be used.

[size=“3”]I obviously still don’t understand, how yii2 is handling errors.

Why have developer implemented an Exception class called[/size] [color="#666600"][size="2"]\[/size][/color][size="2"]yii[/size][color="#666600"][size="2"]\[/size][/color][color="#000088"][size="2"]base[/size][/color][color="#666600"][size="2"]\[/size][/color][color="#660066"][size="2"]UnknownClassException,[/size][/color]

[size=“3”]I assumed, calling a class, which dosn’t exist will execute code,[/size]

[size="3"]which is implemented in catch part of try/catch, but it actually throws out error in browser,[/size]

[size="3"]which is definetly not intended(of me)…[/size]

Error handling is a very big matter in the framework design, and I don’t think I fully understand the concept and scheme of error handling in Yii framework. So I may be wrong but I will try to describe what I think is right. I hope someone will correct me if I’m wrong.

The first thing I think you should note is the fact that your particular try-catch block may be ignored by an internally nested try-catch block.

The following is a pseudo code that tries to illustrate the basic scheme of error handling:




    try {

        doSomething();

        doOther();

        doAnother();

    } catch (Exception $e) {

        handleError($e);

    }

...


public function handleError($e)

{

    echo $e->message;

    exit;

}


public function doSomething()

{

    foo();

    bar();

    ....

    if ($something == "wrong") {

        throw new Exception("Error in doSomething.");

    }

}


public function doOther()

{

    try {

       baz();

    } catch (Exception $e) {

        handleError($e);

    }

}


public function doAnother()

{

    try {

       foobar();

    } catch (Exception $e) {

        log($e->message);

        throw new Exception("Something is wrong. See the log for the detailed information.");

    }

}




When an error occurred in "doSomething", it will be caught by your catch block, because "doSomething" throws an Exception.

But when an error occurred in “doOther”, you won’t get back to your catch block because “doOther” calls “handleError” directly and the process will be terminated there.

And when an error occurred in "doAnother", your catch block will catch an exception because it throws back it. But "doAnother" does not show the original error message for security reason.

This is only a single line of code, but it’s not a light one. PHP has to search EKontak class across your source code using the autoloaders of Yii and Composer. Calling “new EKontak()” is something similar to calling “doOther”, since it has an inner try-catch block that won’t get back to your code.

Another thing you should consider is that there are mainly 2 kinds of exception.

  1. Error that the end users should be informed

  2. Error that only the developer should be informed

And generally speaking you don’t have to worry about the latter kind of error, because Yii will take care of it for you. In debug mode, Yii will show you the detailed information regarding the error using its internal error view to support your debugging. And in the production mode, it will be displayed using an error view for the end users but with a limited information like “something is wrong”, while the detailed error information can be retrieved by the developer from the application log.

I may be wrong, but you are trying to show all the errors including the latter kind to the end users, which is not a good design.