So I have this little bit of code
public function getPrices($debtorId)
{
$priceListId = $this->getPriceListId($debtorId);
if(!$priceListId){
throw new \Exception('No list found for this customer');
}
// doing some operations here that require $priceListId
return $prices;
Up until now, I would have done something like
if(!$priceListId) exit('No list found for this customer');
The difference being, that I could catch the Exception if I want to, while that's not possible with the exit statement.
However, in this case I do want my program to exit. But my IDE warns me that I'm not catching Exceptions. So, should I really do this now:
try {
$prices = $priceHandler->getPrices($debtorId);
} catch(Exception $e) {
exit($e->getMessage());
}
The latter appears to me as unecessary and actually decreasing code quality. So: Is it acceptable to deliberately NOT catch some exceptions? Or should I even get rid of the exception alltogether and just use plain old exit?
I tried searching for this question, but I only got results about people who had technical problems with try/catch not working.
No, you should not catch your exception there if you do not want to.
Even if you want to catch it, it could very easily be somewhere else, so you definitely do not have to wrap this in a try-catch.
Instead, you should tell your IDE that this method is supposed to throw an exception:
/**
* #throws \Exception
*/
public function getPrices($debtorId)
Related
I tried to catch an exception inside a PHPUnit test but it does not work as I expected. The exception seems to be caught in a higher level and I do not understand why.
public function testException()
{
echo 'Enter';
try {
throw new Exception('error.');
} catch (Exception $e) {
echo 'catch Exception';
}
echo 'End';
}
In the output only 'Enter' is visible. I do not reach the 'End'.
(I am using PHP7)
Thanks
Edit:
Replacing all Exception with \Exception solved my issue
Handling exceptions can be tricky, especially when they are called Exception :-)
Just look at all the feedback this (almost the same) question has generated.
Now, the exception is not caught only if does not match to the expected class. In this case it is definitely because of non-precise Exception class names specification, which will most certainly be fixed by specifying them as \Exception.
As smartly put by a commenter from the mentioned question thread:
Without the backslash Exception is specific to the namespace and won't be matched (or caught).
Is there a way to throw an exception in PHP without try and catch?
I mean something like this:
if(!isset($_POST['APIKEY']) || $_POST['APIKEY'] != API_KEY)
throw new Exception(lang("apikey_error"));
Pretty much the whole point of exceptions is to not reflexively catch them.
Exceptions are an error handling mechanism that allows you to propagate errors. That explicitly means that if your application encounters an exceptional state in which it cannot continue working, you signal that by throwing an exception and abandoning the current execution context entirely. If this happens somewhere "at the top" of your application, the application is terminated, because it cannot continue to run. As it should.
Catching exceptions is for when your code is calling a subsystem and that code expects possible errors in that subsystem and knows what to do with them. The subsystem may fail, but the caller can deal with that failure. If the subsystem would be catching its own exceptions... what's the point?
try {
throw new Exception;
} catch (Exception $e) {
// what now?
}
How does the above differ from the below?
// what now?
So, yes, you can and virtually always should throw exceptions without catching them right then and there. Leave the catching up to the caller.
function foo() {
// Something's wrong, can't do my job, I'm outta here!
throw new Exception;
}
try {
foo();
} catch (Exception $e) {
// oh, something's wrong with foo(), let's try bar() instead
bar();
}
Is there any easy way to find out, which types of exception I can expect in try block? Let's say I have:
<?php
try {
foo();
} catch (\A\B\FooException $e) {
} catch (\A\B\BarException $e) {
}
Is there any tool which can inspect the foo() code for me and list all of exceptions types I can expect there? So if there is \A\B\BazException I forgot, I can easily add another catch thanks to that list. For now I use search for "Exception", but sometimes there is to many the same results.
I don´t know any tools to do that. But you can create at least the code block below:
catch (Exception $e) {
mysql_query("INSERT INTO exceptions_tb ('exception_name','expection_message') VALUES ('"+$e->class+"', '"+addslashes($e->message)+"') excetption ", $conn);
}
And after consult the variations of exceptions happened in all your unit tests. Or simply you can do all possible ways and input data types in your unit tests and see what exceptions will arise.
I don´t believe there is a tool that can do this for you also because the tool will need to now all possible inputs and php variables are not predefined types.
...
catch (Exception $oError) {
Logger::logError($oError);
}
class Logger
{
public static function($oError){
// do here detection you like\want
// you can use loops and pre-def. instances of errors
if ($oError instanceof ExceptionCustom)
// some actions
}
...
}
}
class ExceptionCustom extends Exception {
// http://www.php.net/manual/en/language.exceptions.extending.php
//...
}
It's only sample, base thing. You can\should do it more complicated the way you want.
ADDED:
Main thing that you will decide, what error and what you should do, only after you receive exception, and of course you should create default action for it (no matter what exception is thrown).
I'm playing around with custom PHP exceptions for the first time, and would like some help with cleaning up some code. In particular, I'm catching PDO errors, and have written a class to mail myself a stack trace of the errors. The way that I'm currently doing things is as follows:
try {
//db stuff
} catch (PDOException $e) {
throw new My_Own_Exception($e);
exit;
}
where my My_Own_Exception does the job with:
class My_Own_Exception extends Exception
{
/*code to mail myself error info: this part works!
}
While the above works, I feel like I should be able to just write something cleaner such as:
try {
} catch (My_Own_Exception $e) {
exit;
}
where My_Own_Exception is an extension of the PDOException class. A few questions about this: First, is the second way the better approach? Second, if so, is it possible? Third, if it is possible, how do I let PHP know that My_Own_Exception "exists" if My_Own_Exception is never instantiated anywhere? Hopefully the third question makes some sense: my gut tells me that if I can make that happen, then my approach should be possible.
I don't think that an exception is the correct place for logic, it should contain information about the error. A PDOException is useful because you know it originates from your PDO code, if you throw a MyException instead, you need to at least give more (useful) information.
This being set, you should read BiVOC's comment on your original question.
If you have a custom exception handler, you can then differentiate via instanceof.
function exception_handler($exception) {
if ($exception instanceof PDOException) {
//mail
}
//always log/etc.
}
What you are trying to do wont work, because nothing in the PDO code will throw your exception, unfortunately. So you are going to have to throw it yourself, like you were in the first example.
Also, the exit in the first example will never be hit.
In PHP, I sometimes catch some exceptions with try/catch :
try {
...
} catch (Exception $e) {
// Nothing, this is a test that an exception is thrown.
}
With that kind of code, I end up with the variable $e that is created for nothing (lots of resources), and PHP_MD (PHP Mess Detector) creates a warning because of an unused variable.
Starting with PHP 8, it is possible to use a non-capturing catch.
This is the relevant RFC, which was voted favourably 48-1.
Now it will be possible to do something like this:
try {
readFile($file);
} catch (FileDoesNotExist) {
echo "File does not exist";
} catch (UnauthorizedAccess) {
echo "User does not have the appropriate permissions to access the file";
log("User attempted to access $file");
}
With this, for some edge cases where the exception details are not relevant and exception type already provides all the necessary context, it will be possible to catch the exception without creating a new variable.
You can with PHP 8 #see
PHP 5,7
No, but you can unset it.
try {
...
} catch (Exception $e) {
// Nothing, this is normal
unset($e);
}
If it is PHPMD causing this issue then you can suppress the warning.
PHPMD suppress-warnings
class Bar {
/**
* This will suppress UnusedLocalVariable
* warnings in this method
*
* #SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
public function foo() {
try {
...
} catch (Exception $e) {
// Nothing, this is normal
unset($e);
}
}
}
I'm assuming you are only catching the exception because you need to not because you want to.
With PHP 5,7 you have to use a catch if you want to use try and if you use a catch you have to declare a variable.
That's the whole point of exceptions - you can have multiple different catch blocks to catch any exceptions you'd want to handle. The exception's data has to be assigned somewhere, hence the variable. You could just do something like unset($e) inside the catch block if you really don't want to see those warnings... or disable the warnings (generally a bad idea).
I disagree fundamentally with Marc B's and Artefacto's answers. There are cases where ommitting the catch is better or even the only option. Especially when using external libraries (where you have no control over what exceptions are thrown) and/or async operations.
For example:
I want to create a file only if it doesn't exist yet. I'm using an external I/O library. Imagine it has File::exists($fileName) and File::create($fileName) methods.
Option 1 (if ommitting the catch was possible):
try {
File::create($fileName);
}
// Go on with the rest of the code.
Option 2 (without try/catch):
if (!File::exists($fileName))
File::create($fileName);
Here, option 1 is perfectly valid, since option 2 has two important issues:
If multiple threads are running and going through this code section at the same time, it could be that thread A first checks if the file exists. Next, thread B checks if the file exists. They both find that it doesn't exist. Thread A creates the file. Thread B then attempts to create it again and throws an exception even though you're using the if check.
It's very likely that the library itself already performs the !File::exists($fileName) check. Therefore you're wasting a call that is already made.
Note that if File::create throws other exceptions that might be unexpected it would be good to catch those.
Conclusion
Stating that something is never a good idea, is almost never a good idea. There are always exceptions (hehe) to the rule. Like any convention or design pattern, it's just a rule of thumb meant to help less experienced developers make the right decision.
No.
In any case, it's generally a bad idea to catch an exception and do nothing; exceptions exist precisely to force you to handle the exceptional circumstance (otherwise execution is aborted), so it's comprehensible the language doesn't facilitate such a use case.
As of PHP 8.0 it may be typed without variables, but the general case for each Exception is now Throwable. Class Exception implements Throwable.
try {
...
} catch (CustomException) {
// CustomException
} catch (Throwable) {
//All other classes implementing Throwable interface
}