Skip to main content

Does it make sense to throw an exception in a try block in PHP?

Created
Active
Viewed 849 times
28 replies
2

So, does this code make sense, and if yes, under what circumstances?

try {        

        throw new \Exception('First exception...');             

 }

 catch (\Exception $e)

 {      

    throw new \Exception('Second exception...');        

 }

28 replies

Sorted by:
77811129
5
  • 18.5k
  • 1
  • 11
  • 31

It's called "exception chaining": How to implement exception chaining in PHP

77873016
5

The important bit is to pass the original exception. Coded as in the question, you drop the information altogether.

77811599
0
  • 62.3k
  • 16
  • 79
  • 92

Only really useful if you need to do something specific when the exception is thrown. There's a slight performance cost to catching and throwing exceptions, so you generally only do it if you really have to

77812056
0

Thanks, but my problem is, that as the first exception message is not printed out, the second is, and therefore the first exception message is not used.

77812214
0
  • 62.3k
  • 16
  • 79
  • 92

Well if you want to re-throw the original exception in the catch block you can certainly do that. You didn't mention that as the issue originally.

The point still stands though that catching an exception only to then cause an exception again (either the same one or a different one) only has a pretty small number of use cases. You didn't say why you want to do this so it's hard to say whether it makes sense in your particular case or not

77811857
0
  • 33.6k
  • 27
  • 101
  • 149

Why would it not make sense? Isn't throwing an exception the whole purpose of try block?

77812045
1

It does not make sense, as the first exception message is not used at all, only the second one. That's the problem.

77812051
0
  • 33.6k
  • 27
  • 101
  • 149

The first one is used to trigger the second one. What do you mean it's not used? It is caught.

77812055
0
  • 33.6k
  • 27
  • 101
  • 149

Obviously a real code would never look like this, but the exception could be thrown within another function or based on some condition. This is literally how try-catch works.

77812173
0
  • 6.1k
  • 3
  • 36
  • 49

As you wrote "It does not make sense, as the first exception message is not used at all, only the second one. That's the problem.", something with your code seems to be incorrect.
So while this topic might be interesting generally for discussions, to solve your specific problem you should create additionally a question related to your distinct code problem perhaps.

77813234
2
  • 40.8k
  • 11
  • 81
  • 125

Context is important with these things. Yes there are some cases where it does make sense e.g. you want to catch an exception and wrap it in a different exception that you have implemented specific behaviour. The 3rd parameter of the exception constructor is there for this exact use case. Now when it actually makes sense is another story.

In my mind I see the Symfony HttpException class as a good example where you can catch one exception and then wrap it in an HttpException of a given status and let your exception handler return the appropriate response code to the client. When this exception is logged it should ideally include the wrapped exception as well.

I'm sure there's more potential valid use cases but again, context is very important .

77816898
2

Taken as the code is, it does not make sense. The simple reason is that the visible outcome is only caused by the second throw .. statement, the rest could be stripped.

However, I'm halfway sure this is not what you really wanted to ask or it is not really representative for the real code that prompted the question.

77818405
0

What I presented here as code, is a simplifyed version of a real life code, where exactly happens what happens in my sample code. As the original was coming from a professional company (bank sector) codebase, I felt uncertain if this kind of throwing multiple exception really is not good, however I considered it bad code on my own.

77818973
0

Correct me if I'm wrong, but isn't that's the reason why there's a stack trace ?

77876633
0
  • 28.2k
  • 17
  • 117
  • 160

In this case, you lose the stack trace of the first exception, since it's lost completely. In case of proper exception rethrowing/chaining, you'd get 2 (or more) stack traces printed out.

77823775
1

It makes no sense to throw an exception in the catch block. You would rather have a long list of different types of exceptions to catch for efficiency.

77824820
1

Doesn't make sense since php 7.1. Multiple catches allow you to catch different classes of exceptions.

77825782
1

It's not ideal, but you can still do it. There is no defined rule for it.

77876623
0
  • 28.2k
  • 17
  • 117
  • 160

I mean, there's no rule that stops you from randomly generating an empty file somewhere, for no reason, but that doesn't make it a good idea. There's a level for "ideal", there's a level for "non-ideal", but this one goes into the level of "borderline clueless". 😅

77830522
1

First, this code does not make sense because the first exception does not print the message. But, the first exception will be thrown, and the catch block executes.

If you want to print the message of the first exception, you can add $e->getMessage().

But, your code does make sense in some situations.

try {
    $result = 0/0;
} catch(Exception $e) {
    // echo $e->getMessage();
    throw new Exception('The second exception...');
}

This code will throw an exception in the try block. It will be caught by the catch block. And you can throw a custom exception, other than printing the default exception. This code is also the same as your code.

77873728
1

One of the use cases when this might make sense is when the first exception might contain sensitive data that you don't want to get displayed or written in plain text log.

In case like that you catch the exception that might contain sensitive data and throw new exception that describe the problem without revealing sensitive data.

77873834
0

Interesting approach! Thank you!

77876569
3
  • 28.2k
  • 17
  • 117
  • 160

In short: That code, as is, makes no sense at all - no ifs or buts.

Long point: as Olivier mentions, it almost looks like exception chaining (which is a quite normal thing to do).

Proper chaining requires throwing a new exception with the old exception as the previous one. For example: throw new \Exception('Second exception...', 0, $e) (notice the $e).

Additionally, typically you would rethrow as a more specific exception, to be more useful.

And finally, also consider if you really need to catch all \Exception's. In your current case, it is clearly not needed.

79374406
0
  • 5.3k
  • 4
  • 37
  • 50

It is a common pitfall indeed, completely removing the intent of the original code by simplifying too much and therefore only causing confusion. If you want to simplify an example, it still needs to be a realistic one.

77879170
1

Yes, the code makes sense in the context of exception handling in PHP. It demonstrates a scenario where an exception is explicitly thrown inside a try block, which is then caught by the catch block. The catch block itself throws a new exception.

This pattern can be useful in a situation where you want to transform or reclassify an exception. For instance, you might catch a generic exception and then throw a more specific exception type that is more meaningful for the surrounding code or the application's error handling strategy.

However, it's important to note that this approach will lose the original exception's stack trace unless it's explicitly preserved or logged. This could potentially make debugging more challenging.

79373152
1

Technically, there is nothing wrong with that.

Semantically, you also need it, but it can involve quite subtle considerations.

Here is the idea: catch should be used rarely and placed only in some strategic points in the scope that I usually call the scope of competency.

I'll explain: the point of throwing the exception can be placed in an agnostic level of the code, for example, general I/O. Sometimes, you need to catch the exception on the same or another agnostic level, say, adjust some data, or recover from something. But the issue remains unresolved, and you need to delegate further exception processing up the stack. And next catch point may come at some semantic layer.

In that layer, a technical, say, I/O exception will be not informative enough. Let's jump to the very top of the stack: the exception exposed to the final user. This user has no idea of the existence of some stream or file, that person needs to find out what it means semantically. To achieve that, you need to catch an exception in some intermediate level that knows the consequences of the exception in some semantic sense, known by the user. To achieve that, this semantic layer catches the abstract-layer exception and throws another exception, defined in a semantic layer. In principle, the original exception can be packed in a new exception instance as an internal exception but this is not the rule. The point is that the presence of those competency points requires the developers to throw an exception of a more semantic type.

79374290
0

It can make sense if you need to catch, manipulate, in short work on an exception that might be thrown by a library or some third-party code (that you can't or don't want to modify).

Suppose \ExternalObject::something() can throw exceptions \AlphaException or \BetaException.

I use \ExternalObject::something(), but I don't particularly care about the distinction between the various exceptions OR I want to throw my own \MyCustomException, for whatever reason.

So:

try {
    \ExternalObject::something()
} catch (\AlphaException|\BetaException $e) {
    throw new \MyCustomException(sprintf('Thrown know exception `%s` with message: `%s`', $e::class, $e->getMessage()));
} catch (\Exception) {
    throw new \MyCustomException(sprintf('Thrown unknown exception `%s` with message: `%s`', $e::class, $e->getMessage()));
}

(I haven't checked the code for accuracy, but that's the gist of it)