PostNuke Help |
||
|---|---|---|
Previous |
Next |
|
PostNuke is capable of error handling through a powerful exception handling system. Since the PHP language doesn't support language-level exceptions, PostNuke provides an artificial mechanism to deal with exceptions. PostNuke divides exceptions into two types: system exceptions and user exceptions. System exceptions are used by PostNuke API functions, but you can use them if it's meaningful in that such situation; for example consider the DATABASE_ERROR exception, you are strongly encouraged to use this exception when a database error occurs and not to use your own exception. As another example consider the BAD_PARAM exception, you should choose to use that exception in your module functions and API functions when passed parameters are considered wrong. Finally system exceptions are well known exceptions for which PostNuke can undertake particular actions like logging or emailing, on the other hand user exceptions are not known by PostNuke, and since they are indistinguishable, PostNuke will treat them as if they were all the same thing.
Another good point in distinction between system and user exceptions is the fact that you should not leave uncaught user exceptions as you can do for system exceptions. Hence you should catch all user exceptions instead of throwing them back to PostNuke, as user exceptions can be seen as soft exceptions, so you could be in the position of doing other actions and/or returning a properly formatted error message that will look better than the default PostNuke exception caught error message. However, it's not illegal to throw back user exceptions to PostNuke, so fell free to do that if it's the case. On the other hand you should avoid catching system exceptions, except in particular cases. A system exception is an hard exception, which means that something very wrong happened and PostNuke should be notified of that. You achieve this simply by throwing back system exceptions. Also, there are particular circumstances in which you could and perhaps should catch system exceptions, for example consider the pnUserGetVar() API function: it raises a NO_PERMISSION system exception if you don't have right permission, however you weren't in the position to get access level for user variables, so it's perfectly acceptable here to catch this exception and go ahead when it's meaningful to go ahead.
Here we begin by exposing how to catch exceptions. When a function, that pontetially can raise exceptions, outcomes with a void value you MUST check if some exception was raised. You can do that by calling the pnExceptionMajor() function and comparing its return value with the PN_NO_EXCEPTION constant. If they are different you know that an exception was raised. The pnExceptioMajor() API call can return one of these values: PN_NO_EXCEPTION, PN_USER_EXCEPTION, PN_SYSTEM_EXCEPTION. Obviously the value PN_NO_EXCEPTION indicates that no exception was raised, PN_USER_EXCEPTION indicates that a user exception was raised, and PN_SYSTEM_EXCEPTION indicates that a system exception was raised. When you see that an exception was raised you have two options: throw it back or handle it. To throw back an exception you have only to return with a void value. To handle an exception you have to check for the exception type, id and value if there is one.
Consider the following example:
$res = pnModFunc('MyModule', 'user', 'MyFunc');
if (!isset($res) && pnExceptionMajor() != PN_NO_EXCEPTION) {
// Got an exception
if (pnExcepionMajor() == PN_SYSTEM_EXCEPTION) {
return; // throw back
}
// Got a user exception
if (pnExceptionId() == 'MyException1') {
$value = pnExceptionValue();
$output->Text("Syntax error at line: ".$value->lineNumber);
} elseif (pnExceptionId() == 'MyException2') {
/* Do something useful */
} else { // MyException3
/* Do something useful */
}
// reset exception status
// NOTE: it's of vital importance to call this function
// before returning
pnExceptionFree();
return $output->GetOutput();
}
To throw an exception you use a unique function: pnExceptionSet(). You simply call it by passing the exception major, id and value if one; and after this call you return void.
Consider the following example:
class MyException1
{
var $lineNumber;
}
/* ... */
MyModule_user_MyFunc()
{
/* ... */
if ($syntax == false) {
// Syntax error
$exc = new MyException1;
$exc->lineNumber = $line;
pnExceptionSet(PN_USER_EXCEPTION, 'MyException1', $exc);return;
}
/* ... */
pnExceptionSet(PN_USER_EXCEPTION, 'MyException2');
/* ... */
pnExceptionSet(PN_USER_EXCEPTION, 'MyException3');
/* ... */
return true;
}
Note that no value is associated to MyException2 and MyException3, so there is no need to create a class for exception value. As you can see exception handling is very powerful but also boring and tedious. However you can always choose to not use user exceptions and always throw back system exceptions. But keep in mind that good error handling is not something that should be left for last. It should be part of the development process. Note that it is wrong to not check exception status after a call to a function that can pontentially raise something. Also note that if you choose to handle one or more exceptions you MUST call pnExceptionFree() before exiting, otherwise the trust relationship on which the exception handling mechanism is based won't work and very bad things will happen. If you aim to code an official PostNuke module, you MUST always check for possibly raised exceptions and not code with the thought that something will never happen; you MUST also raise DATABASE_ERROR in every function that do queries. To get a better understanding of exception handling functions you should now look at PostNuke API Command Reference.
Previous |
Next |