try catch vs if else in PDO and some other things
There is this question that I found:
What is the advantage of using t开发者_运维问答ry {} catch {} versus if {} else {}
If you can add anything to it then please do as I am new to PDO, also what does this mean;
$dbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
On the MySQL website it says "ensures the creation of exceptions rather than errors" but I do not understand this, can anyone please elaborate on it please.
Exceptions are catchable via try/catch and are classes with properties, while proceedural errors cannot and are not. Proceedural errors are instead handled by PHP's native error handling.
You can observe the behavior difference by manually triggering them.
to throw an Exception:
throw new Exception();
to trigger a proceedural error:
trigger_error($message, U_USER_ERROR);
Exceptions are bassically the OO way of error handling. Find more information about Exceptions here: http://php.net/manual/en/language.exceptions.php
Well, they are pretty similar. In PHP native error handling you can trow your own errors with trigger_error($error, [$level])
as you can throw your own exceptions with throw new MyException($error)
; you can set a default error handler with set_error_handler()
which will manage all PHP error (except parsing) your own way as you can set a default exception handler with set_exception_handler()
. Both PHP native errors and exceptions are automatically triggered/thrown somehow: PHP native errors compiling the script, exceptions if you are using specific items such as (PDO) or something.
Now let's try the same code with different approaches: With PHP native errors you can do things such as:
$db = new Database();
if ($db === NULL) { trigger_error("Cannot connect to the database", E_USER_ERROR); }
$result = $db->query("UPDATE charlieiscool SET iloveunicorns = 1 WHERE userid = 1");
if (!$result) { trigger_error("Error updating table", E_USER_ERROR); }
$file = 'log.php';
if (!file_exists($file) or !file_get_contents($file)) { trigger_error("$file not found", E_USER_ERROR); }
require($file);
I think this does not really need any explanation. If an error is triggered, the entire script is skipped and you see the error. There are no more things you can do; you could set E_USER_ERROR
or E_USER_NOTICE
or E_USER_WARNING
and handle them differently, but you have not that big choice. Now take a look at a possible OOP approach with try{} catch() {}
blocks:
try {
$db = new Database();
if (!$db) { throw new DBEx("Cannot connect to the database"); }
$result = $db->query("UPDATE charlieiscool SET iloveunicorns = 1 WHERE userid = 1");
if (!$result) { throw new QueryEx("Query failed"); }
} catch (PDOException $e) {
echo $e->getMessage();
} catch (DBEx $e) {
$e->customFunction();
} catch (QueryEx) {
$e->customFunctionForQuery();
}
try {
$file = 'log.php';
if (!file_exists($file) or !file_get_contents($file)) { throw new FileEx("$file does not exists"); }
require($file);
} catch (FileEx) {
$e->fileGenerate();
$e->logError();
}
The main difference is that if the first try{}
block throw an exception the second try{}
will be executed any way. In fact if an exception is thrown, only the rest of the script inside that try{}
block will be skipped.
Another difference (the one i love most) is that you can create several classes (extending mains Exception
or PDOException
or others) and customize very much your error handling behavior. You have unlimited possibilities to customize your classes, adding functions, editing already existing ones. You can add specific function (such as $e->fileGenerate();
) and call them inside the catch() {}
block where needed.
Notice also that if you want your entire script to stop if an error occurred, means that that error needs trigger_error()
; instead if you want that an error only stops a specific block of code related to that error then it's time for try and catch.
You should not use one replacing the other, you should use one beside the other evaluating each errors as it is.
By the way PDO::setAttribute()
change default values and options in your database handler. You can for example change your default fetch (used in PDOStatement::fetch()
) with $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
.
References:
- PDO::setAttribute()
- set_error_handler()
- set_exception_handler()
- Exceptions
- Predefined exceptions
精彩评论