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.
Related
I perfectly understand the nuances of the (try/throw/catch) block.
What I don't understand is:
If we gonna use an IF (or any control structure) inside our try block anyway in order to test if a condition is met, only then, 'throw' an exception if the results of that test is false, then... in my opinion: throw/generate an exception is useles; because if a condition is not met, we can simply print an error message, call a function, instantiate a class, redirect to another location, etc.
Another story would be, if for instance, a variable was not initialized, we enclose that variable inside a try{} block, echo the variable, and from that point onward, everything will be handle by the catch() block because the try block raises an error; and since the try/catch blocks talk each other, the catch block will catch every error that was originated from his corresponding try block. However, you can set a custom error message inside yout try block (optional).
What I've read so far:
every results from searching: if vs. try
I do see the difference.
But I can not understand why some people choose try/throw/catch over if...else...switch...while... etc.
As far I can see, try/throw/catch can be used for debugging, though.
One benefit of exceptions over if/then is that you can wrap try/catch around a large block of code. It will be triggered if an error happens anywhere in the block.
try {
$db = db_open();
$statement = $db->prepare($sql);
$result = $statement->execute($params);
} catch (Exception $e) {
die($e->getMessage());
}
With if/then, you would have to perform a test at each step.
$db = db_open();
if (!$db) {
die(db_connect_error());
}
$statement = $db->prepare($sql);
if (!$statement) {
die(db_error($db));
}
$result = $statement->execute($params);
if (!$result) {
die(db_error($db));
}
As you said, it's a lot of overhead to throw an exception inside a try/catch block and catch it immediately.
try {
if (...) {
// good, do no throw
} else {
throw new Exception();
}
} catch ($e) {
// handle exception
}
This should be replaced by:
if (...) {
// good
} else {
// handle error, no exception
}
Exceptions are useful because they bubble up. So imagine if you have this code instead:
function bla() {
try {
tryToDoSomething();
} catch ($e) {
// handle error
}
}
function tryToDoSomething() {
if ($somethingNotAvailable) {
throw new Exception();
}
doSomething();
}
In this case, the function that defines the try/catch is NOT the one throwing the exception. tryToDoSomething() does not know how to handle the errors so it will let parent methods to take care of it. The exception can bubble up the call stack until someone catches it and handles the error. That's how exceptions can actually be useful :)
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.
Since a short period of time I'm working with Try Catch in PHP. Now, every time a new error is thrown you get a fatal error on the screen, this isn't really user friendly so I was wondering if there's a way to give the user a nice message like an echo instead of a fatal error.
This is the code I have now:
public static function forceNumber($int){
if(is_numeric($int)){
return $int;
} else {
throw new TypeEnforcerException($int.' must be a number');
}
}
public function setStatus($status) {
try {
$this->status = TypeEnforcer::forceInt($status);
} catch (TypeEnforcerException $e) {
throw new Exception($e->getMessage());
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
This is best solved with a frontend controller that is able to catch all uncatched exceptions:
<?php
require('bootstrap.php');
try {
$controllerService->execute($request);
} catch (Exception $e) {
$controllerService->handleControllerException($e);
}
You can then write code to return the internal server error because an exception signals an exceptional case so it normally is an 500 internal server error. The user must not be interested what went wrong other than it just didn't work out and your program crashed.
If you throw exceptions to give validation notices you need to catch those in a different layer (and you're probably doing it wrong if you use exceptions for that).
Edit: For low-level functions, because PHP is loosely typed, if a function expects and int, cast to intDocs:
public static function forceNumber($int){
$int = (int) $int;
return $int;
}
this will actually force the integer. In case the cast is not possible to do (e.g. $int it totally incompatible) PHP will throw the exception for you.
The example is a bit akward because by the method's name you use it to validate some number and provide an error if not (here wrongly with an exception). Instead you should do some validation. If you expect wrong input, it's not an exceptional case when wrong input is provided, so I would not use exceptions for that.
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.
Which would you recommend?
Return an error code, such as E_USER_ERROR from a function, and determine proper message higher up:
function currentScriptFilename()
{
if(!isset($_SERVER['SCRIPT_FILENAME']))
{
//This?
return E_USER_ERROR;
}
else
{
$url = $_SERVER['SCRIPT_FILENAME'];
$exploded = explode('/', $url);
return end($exploded);
}
}
Execute trigger_error() from the function, with a specific error message:
function currentScriptFilename()
{
if(!isset($_SERVER['SCRIPT_FILENAME']))
{
//Or this?
trigger_error('$_SERVER[\'SCRIPT_FILENAME\'] is not set.', E_USER_ERROR);
}
else
{
$url = $_SERVER['SCRIPT_FILENAME'];
$exploded = explode('/', $url);
return end($exploded);
}
}
I am not sure if I will regret having put a bunch of error messages in my functions further down the line, since I would like to use them for other projects.
Or, would you recommend something totally different?
Do not mix the matters.
Error notification and error handling are different tasks.
You have to use both methods simultaneously.
If you think that $_SERVER['SCRIPT_FILENAME'] availability is worth an error message, you can use trigger error. However PHP itself will throw a notice if you won't check it.
If you want to handle this error, just check this function's return value.
But I would not create a special function for this task.
So,
if (!$filename = basename($_SERVER['SCRIPT_FILENAME']) {
// do whatever you want to handle this error.
}
would be enough
Exceptions could be useful to handle errors, to know if we had any errors occurred.
A simple example:
try {
$filename = basename($_SERVER['SCRIPT_FILENAME'])
if (!$filename) throw new Exception("no filename");
$data = get_some_data_from_db() or throw new Exception("no data");
$template = new Template();
//Exception could be thrown inside of Template class as well.
}
catch (Exception $e) {
//if we had any errors
show_error_page();
}
$template->show();
3.Use exceptions.
If this is the route you are going, I'd rather recommend throwing Exceptions rather then returing an E_ERROR (E_USER_ERROR should be used), as this is just an integer, and possibly a totally valid return for your function.
Advantages:
- Throwing of an Exception cannot be interpreted as anything else then an error by mistake.
- You keep the possibility to add a descriptive error message, even though you don't handle the error at that point/
- You keep a backtrace in your Exception.
- You can catch specific exceptions at specific points, making the decision where in your project a specific type of error should be handled a lot easier.
If not using exceptions which you should be, use trigger_error().
If it is an error you'd like to deal with, try returning FALSE like a lot of the in built functions do.
If you do use exceptions, catch them like this
try {
whatever()
} catch (Exception $e) {
// handle however
}