Is it possible to display all catches instead of only one? In the example below, what if both the username and email are wrong, can I output both instead of just one.
try {
// Code here
}
catch(WrongUsername $e) {
echo 'Your username is wrong.'
}
catch(WrongEmail $e) {
echo 'Your email is wrong too.'
}
You can probably loop thru all the validation rules and cathc all errors.
$errors = [];
foreach($rules as $rule){
try{
validate($input, $rule);
}catch(Exception $e){
$errors[] = $e->getMessage();
}
}
But then I don't see any reason to use try-catch at all.
This doesn't really make a lot of sense within PHP - it's dynamically, not fixed typed, and does not support overloading. In your example is 'WrongEmail' the class of the exception or the exception message? Is there a benefit to sub-classing exceptions?
If it's the message property of the exception, then change it to use something more informative...
try {
...
if (!preg_match($pattern, $username))
throw new Exception('Your username is wrong.');
...
} catch ($e) {
echo $e->message;
}
If you have a good reason for sub-classing your exceptions...
try {
...
} catch ($e) {
switch (get_class($e)) {
case 'WrongUsername':
echo 'Your username is wrong.';
break;
case 'WrongEmail':
echo 'Your email is wrong.'
break;
...
}
}
But exceptions are part of a flow control structure - when you throw an exception you change the flow of execution. A try{} block will never raise more than one exception. In terms of programming style it's debatable whether you should actually use exceptions at all for this kind of operation.
If you want to check a set of pre-conditions and deal with each failed requirement then don't use this construct.
Related
i'm sending emails via phpmailer and i want to override the exceptions as when you send an email and that fail you can have the error message via :
echo json_encode"{$mail->ErrorInfo}";
but when the error is
"Empty body"
i would like to display something else.
Any solution ? Thanks
$new_msg = json_encode"{$mail->ErrorInfo}";
if ($new_msg == 'Empty body') {
throw new CustomException("You custom message ");
}
Wherever you are calling this function, catch the expectation there and show it to the user.
try {
if ($new_msg == 'Empty body') {
throw new CustomException("You custom message ");
}
} catch (CustomException $ex) {
//This is where you can have your own handling, exceptions that you want to handle separately
} catch (Exception $ex) {
// this part will handle general exceptions
// and show user some general error message
}
You can put your echo in a variable and then do an if check to display something else.
$new_msg = json_encode"{$mail->ErrorInfo}";
if ($new_msg == 'Empty body') {
echo 'You put here whatever you want';
} else {
echo json_encode"{$mail->ErrorInfo}";
}
Just catch the Exception and do something completely different!
try {
$something->thatWillThrowAnException();
} catch (Exception $e) {
// Do anything you want here!
}
I have a problem where I want to catch all exception except descendants of my custom exception.
Maybe bad design, but here it is (Simplified and names changed, but the code is quite accurate):
function doStuff()
{
try {
// code
if (something) {
// manually throw an exception
throw StuffError("Something is bad.");
}
// a third-party code, can throw exceptions
LibraryClass::arcaneMagic();
} catch (Exception $e) {
throw new StuffError("Error occured while doing stuff: "
. $e->getMessage());
}
}
/** My custom exception */
class StuffError extends Exception
{
function __construct($msg) {
parent::__construct('StuffError: ' . $msg);
}
}
However, the issue here is that I don't want the try-catch to intercept the manually throws StuffError. Or, seamlessly rethrow it or something.
As it is now, I'd get:
StuffError: Error occured while doing stuff: StuffError: Something is bad.
I want just:
StuffError: Something is bad.
How would I do it?
You can have multiple catch clauses, and the first one that matches will be the one that runs. So you could have something like this:
try {
do_some_stuff();
}
catch (StuffError $e) {
throw $e;
}
catch (Exception $e) {
throw new StuffError(Error occurred while doing stuff: " . $e->getMessage());
}
But you might want to rethink wrapping stuff like this. It obscures the real cause of the error. For one thing, you lose the stack trace. But it also complicates error handling, since now someone can't differentiate exception types the way you're trying to do, short of trying to parse the exception message (which is rather an anti-pattern in itself).
I might be misinterpreting you, but I think this is what you're looking for:
...
} catch (Exception $e) {
if (get_class($e) == 'StuffError' || is_subclass_of($e, 'StuffError')) {
throw $e;
} else {
throw new StuffError("Error occured while doing stuff: "
. $e->getMessage());
}
}
...
Replace your catch statement with the code above. It checks to see if the exception is a StuffError or a child class of StuffError. I'm still very confused at why you would need to throw a StuffError exception after you catch, but maybe that's just some weirdness coming from translating/cleaning your code.
This question is about the best way to execute code outside of try block only if no exception is thrown.
try {
//experiment
//can't put code after experiment because I don't want a possible exception from this code to be caught by the following catch. It needs to bubble.
} catch(Exception $explosion) {
//contain the blast
} finally {
//cleanup
//this is not the answer since it executes even if an exception occured
//finally will be available in php 5.5
} else {
//code to be executed only if no exception was thrown
//but no try ... else block exists in php
}
This is method suggested by #webbiedave in response to the question php try .. else. I find it unsatisfactory because of the use of the extra $caught variable.
$caught = false;
try {
// something
} catch (Exception $e) {
$caught = true;
}
if (!$caught) {
}
So what is a better (or the best) way to accomplish this without the need for an extra variable?
One possibility is to put the try block in a method, and return false if an exception is cought.
function myFunction() {
try {
// Code that throws an exception
} catch(Exception $e) {
return false;
}
return true;
}
Have your catch block exit the function or (re)throw/throw an exception. You can filter your exceptions as well. So if your other code also throws an exception you can catch that and (re)throw it. Remember that:
Execution continues if no exception is caught.
If an exception happens and is caught and not (re)throw or a new one throw.
You don't exit your function from the catch block.
It's always a good idea to (re)throw any exception that you don't handle.
We should always be explicit in our exception handling. Meaning if you catch exceptions check the error that we can handle anything else should be (re)throw(n)
The way I would handle your situation would be to (re)throw the exception from the second statement.
try {
$this->throwExceptionA();
$this->throwExceptionB();
} catch (Exception $e) {
if($e->getMessage() == "ExceptionA Message") {
//Do handle code
} elseif($e->getMessage() == "ExceptionB Message") {
//Do other clean-up
throw $e;
} else {
//We should always do this or we will create bugs that elude us because
//we are catching exception that we are not handling
throw $e;
}
}
When throwing exceptions in the following auth class example is it recommended to throw a different exception for each situation to be handled, eg:
addUser(...) {
// normal database code here...
switch(TRUE) {
case ($username_exists):
throw new UserExists('Cannot create new account. Account username ' . $un . ' already exists.');
case ($email_exists):
throw new EmailExists('Cannot create new account. Account email ' . $email . ' already exists.');
}
}
//to be called externally by...
try {
$auth->adduser(...);
} catch (UserExists) {
$output = 'That username is already taken.';
} catch (EmailExists) {
$output = 'That email is already being used.';
} catch (AuthException $e) {
$output = $e->getMessage();
}
echo $output;
}
or is it recommended to throw a general "type" of exception with a unique exception code? eg...
addUser(...) {
// normal database code here...
switch(TRUE) {
case ($username_exists):
throw new AuthException('Cannot create new account. Account username ' . $un . ' already exists.', 10);
case ($email_exists):
throw new AuthException('Cannot create new account. Account email ' . $email . ' already exists.', 20);
}
}
//to be called externally by...
try {
$auth->adduser(...);
} catch (AuthException $e) {
switch($e->getCode()) {
case 10:
$output = 'That username is already taken.';
break;
case 20:
$output = 'That email is already being used.';
break;
default:
$output = $e->getMessage();
}
echo $output;
}
I ask because I'm new to exceptions and both solutions seem equally viable. Perhaps there are other solutions entirely?
Interesting side-note: I didn't realize I was asking a "what's your preference" question until after receiving a few answers. I anticipated a single recommended method.
I wouldn't say one way is right and one way is wrong - and asking a "is this way recommended versus this way" can easily stir up a large pot if the question hits the right nerve in a large group.
Regarding your question specifically, both are valid and acceptable ways to throw different types of exceptions - and I've seen both quite frequently.
In large-scale applications in just about every language, however, I see the bottom method more often than not - and it's also my own personal style/preference. I think that throwing a single "type" of exception, AuthException, and specifying an exception-code is very clear and concise.
If you want it to be more descriptive (from a programming standpoint), you can use an pseudo-enum* setup for the codes to give a user-friendly description:
class AuthExceptionCode {
const USER_EXISTS = 0;
const EMAIL_EXISTS= 1;
// ....
}
To throw the exception with the code:
throw new AuthException('error message', AuthExceptionCode::USER_EXISTS);
If you have an actual custom-Exception class, i.e. - you extend Exception, you can place the codes direction in the class itself:
class AuthException extends Exception {
const MISC = -1;
const USER_EXISTS = 0;
const EMAIL_EXISTS= 1;
public function __construct($message, $code = self::MISC) {
switch ($code) {
case self::USER_EXISTS:
// example on how to access the codes from within the class
// ...
* Enumerations are not native to PHP, so using const is the easiest method (without using a 3rd-party class/plugin.
In general, I think the best practice is that an exception should encompass a single exceptional condition. Take the SPL exceptions, for example. Would you throw InvalidUserArgumentException and InvalidEmailArgumentException? Nope. You'd throw the SPL InvalidArgumentException and just change the exception message based on the details (e.g. "Invalid user" or "Invalid email"). That said, IMHO, you should use a single AuthException and just vary the message (like you did in your 2nd example), only instead of using codes and a switch, just output the exception message directly:
try {
$auth->adduser(...);
} catch (AuthException $e) {
$output = $e->getMessage();
}
echo $output;
I prefer the top way where you have a separate catch statement for each exception that can occur, but it depends.. If you find yourself have really long exception class names where it's difficult to understand their meaning, then I would group them up a bit.
if ($disponivel === 0)
{
$razao = $check->cd->reason;
$mensagem = "the domain isn't available. Reason: ".$razao;
}
elseif($disponivel === 1)
{
$mensagem = "the domain doesn't exist - free to register.";
}
return $mensagem;
}
else
{
throw new EppCommandsExceptions('Domain isn't supported - '.$result->msg, $codigo);
}
Do you see those $mensagem strings? They are also error messages and my question is, instead of having $mensagem displaying some error messages, can we use several throw exceptions instead?
Update:
I DO NOT mean to throw the exceptions all at once. Each exception at his time.
Thanks in advance,
MEM
You can't throw multiple, but since PHP 5.3 you can supply previous to Exception's constructor to create a linked list of exceptions.
For example, here's a 3-item chain:
$a = new Exception('Exception a');
$b = new Exception('Exception b', 0, $a);
throw new Exception('Exception c', 0, $b);
Then, in your exception handler, you can traverse through the chain with getPrevious
do {
printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), get_class($e));
} while($e = $e->getPrevious());
You mean something like
else {
throw new XException(...);
throw new YException(...);
throw new ZException(...);
}
... and all of them are thrown "at once"?
No, thats not possible and wouldn´t make too much sense imho. How should the client code catching these exceptions look?
Furthermore you shouldn´t use exceptions as a replacement for normal flow control structures, exceptions should only handle, well, exceptional errors, like not being able to connect to a database etc.
You could implement another custom exception class which takes an array of errors as an argument, and the client code can do things like:
catch(SomeException $e) {
$messages = $e->getErrorMessages();
}
As I don´t speak the language your language, I cant really tell what you are trying to do in that code bit you posted, otherwise I could suggest something more specific.
EDIT/UPDATE:
#MEM thanks for updating your code with english error messages. Are you implementing something like a domain registration service?
Of course, this is a bit of a difficult topic as everbody has his preferences, but I wouldn´t throw an exception if e. g. the user tried to register a domain thats already been used by someone else. This is not an exceptional state, this is to be excepted. I would make a validation class/method which collects these error messages which in turn get displayed to the user.
When would I throw an exception in an app like yours? I don´t know much about domain registration, but if you are fetching the info whether a domain is free or not from a remote server/webservice and this webservice is down, then I would throw an exception. It gets caught in the Controller (I image a MVC web app) which in turn replies to the client with a "Server down, please try again later" message.
you can throw and catch different exceptions.
If all you want to do is print the error, you can throw same type of exceptions aswell. But I'm going to assume you need different approach to each case
function myFunction() {
if($a) {
throw new AException('A Error');
} else if($b) {
throw new BException('B Error');
} else if($c) {
throw new CExceptıon('C Error');
}
}
try {
myFunctıon();
} catch (AException $aException) {
echo $aException->getMessage();
} catch (BException $bException) {
echo "this is a terrible case, don't do that again pls";
$mydbobject->rollback();
} catch (CException $cException) {
mailDevTeam("the server made a boo boo");
}
Of course, just subclass the base exception for every message.