Xaraya M. Canini 
Request for Comments: 0018 Xaraya Development Group 
Category: Informational May 2002 

RFC-0018: Exception Handling System

Status of this Memo

This memo provides information for the Xaraya community. It does not specify an Xaraya standard of any kind. Distribution of this memo is unlimited.

Copyright Notice

Copyright © The Digital Development Foundation (2002). All Rights Reserved.

Abstract

This document describes the Exception Handling System technology, an artificial exceptions handling mechanism built on top of the PHP language. This document is constantly subject to revisions. This isn't the final version of the document.


Table of Contents


1.  Introduction

Since the PHP language does not provide native exception handling support (as of writing), we need to create an artificial layer to handle them. The way this document proposes to achieve this goal is closely inspired at the way used by CORBA in the C language mapping. In the case of CORBA the C language mapping imposes that every IDL method accept as last parameter a CORBA_Environment type. We can avoid to use a CORBA_Environment-like parameter for all functions, thanks to, firstly, the non-strongly-typed return values we have in PHP, and secondly, the single threaded policy we adopted in Xaraya.


2. Handling exceptions

Here we introduce the following terminology:

Caller is the piece of code that call a function.
Called is the piece of code that used by Caller can raise exceptions.

Callers can notice of exceptions firstly by checking the called function return value and secondly by calling the xarCurrentErrorType function.

The Xaraya Exception Handling System provides useful functions to deal with exceptions. Their signatures are:

void xarExceptionSet($major, $exception_id, $param = NULL); integer xarCurrentErrorType(); string xarExceptionId(); object xarExceptionValue(); void xarExceptionFree();

2.1 xarCurrentErrorType

xarCurrentErrorType allows the caller to establish whether an exception was raised, and to get the type of raised exception. The major XAR_NO_EXCEPTION identifies the state in which no exception was raised.

2.2 xarExceptionSet

xarExceptionSet allows a function to raise an exception. The caller must supply a value for the major parameter. The major parameter can have one of the values XAR_NO_EXCEPTION, XAR_USER_EXCEPTION, or XAR_SYSTEM_EXCEPTION. The value of the major parameter constrains the other parameters in the call as follows:

If the major parameter has the value XAR_NO_EXCEPTION, this is a normal outcome

to the operation. In this case, both exception_id and param must be NULL. Note that it is not necessary to invoke xarExceptionSet to indicate a normal outcome; it is the default behavior if the method simply returns.

For any other value of major it specifies either a user-defined or system

exception. The exception_id parameter is the ID representing the exception type. If the exception is declared to have members, the param parameter must be the exception struct (PHP class) containing the members. If the exception has no members, param must be NULL.

2.3 xarExceptionMajor (Deprecated)

Replaced with xarCurrentErrorType commencing in Version 0.9.8

2.4 xarExceptionId

xarExceptionId returns the string identifying the exception. The character string contains the ID for the exception (its PHP class name). If invoked when no exception was raised a void value is returned.

2.5 xarExceptionValue

xarExceptionValue returns an object corresponding to this exception. If invoked when no exception or an exception for which there is no associated information was raised, a void value is returned.

2.6 xarExceptionFree

xarExceptionFree makes a reset of current exception status, it's a shortcut for xarExceptionSet (XAR_NO_EXCEPTION, NULL, NULL). You must always call this function when you handle a catched exception or equivalently you don't throw the exception back to the callers chain.

2.7 Usage of exception handling functions

To get an overview on their usage consider the following example:

class ?MyException { 
    var $msg;
} 
function ?MyModule_userapi_?MyFunc() { /* Called */ /* ... */ } 
?... 
/* Caller */ /* ... */ 
$res = xarModAPIFunc('?MyModule', 'user', '?MyFunc'); if (!isset($res) && xarCurrentErrorType() != XAR_NO_EXCEPTION) { 
    // Got an exception
    switch (xarCurrentErrorType()) {
       case XAR_USER_EXCEPTION:
           if (xarExceptionId() == '?MyException') {
          $value = xarExceptionValue();
          die("Caught ?MyException, msg: ".$value->msg);
       }
       break;
       case XAR_SYSTEM_EXCEPTION:
           die("Caught system exception: ".xarExceptionId());
       break;
    }
} 
/* ... */
                     

2.8 Throw back mechanism

An important thing to take care of is the throw back mechanism. Even if with this proposed solution there is not a break in the program flow when an exception is raised, the Exceptions Handling System allows you to apply the concept of throwing back an exception. And it's also very simple to do that, you've only to return with a void value after you catch an exception. Consider the following example:

function foo() { 
    $res = xarModAPIFunc('?MyModule', 'user', '?MyFunc');
    if (!isset($res) && xarCurrentErrorType() != XAR_NO_EXCEPTION) {
        // Got an exception, throw it back
        return;
    }
} 
function bar() { 
    $res = foo();
    if (!isset($res) && xarCurrentErrorType() != XAR_NO_EXCEPTION) {
        // Got an exception
    // Real exception handling
        switch (xarCurrentErrorType()) {
           case XAR_USER_EXCEPTION:
               if (xarExceptionId() == '?MyException') {
              $value = xarExceptionValue();
              die("Caught ?MyException, msg: ".$value->msg);
               }
           break;
           case XAR_SYSTEM_EXCEPTION:
               die("Caught system exception: ".xarExceptionId());
           break;
        }
    }
} 
                                        

As you can see in the above example we're delegating to another piece of code the real exception handling.


3. Xaraya integration

To best integrate the Exceptions Handling System into Xaraya we need to define a superset of well known exceptions called System Exceptions and to make the Xaraya APIs compatible with Exceptions Handling System. Modifications to APIs involve the usage of System Exceptions. To get an example of what is a System Exception consider the case in which you're calling an API with a non existent user id. In that case you're violating the Xaraya integrity, so it makes sense to raise an exception of type ID_NOT_EXISTS internally in the API function. For another example you could recall the xarModAPIFunc function. Its purpose is to call an API module function and returns the outcome value of the called API module function. But what's happen if xarModAPIFunc can't call the function you've indicated. As you can read in Xaraya API Command Reference, xarModAPIFunc will return false if the module function does not exist or void for an internal error. By doing so xarModAPIFunc vincolates your module API functions to never return void or false because the caller can't distinguish these values from an error condition in xarModAPIFunc. In the other hand if xarModAPIFunc could raise exceptions your module API functions could return false and void as well, since you're allowed to discover error conditions with the Exception Handling System and not by relaying on return value. As you can see there are many advantages in exceptions but we must keep the Xaraya API as backward compatible as possible. Consider also that exceptions go well not for all error conditions, if you're doing that probably you're wrong. Boolean functions go very well in many cases, and most of Xaraya API functions can indicate particular errors with the false return value. Exceptions have to be used when there's a real needing of them, and not as a replacement for the false return value. The changes that have to be done in Xaraya API must be minimals, and relay only on System Exceptions.

3.1 Xaraya System Exceptions

The Exceptions Handling System need to be closely integrated with Xaraya. To achieve this goal the well known System Exceptions take care of Xaraya architecture, so we will refer to them as Xaraya System Exceptions. A system exception always contains as exception value a PHP class so defined:

class ?SystemException { 
    var $message;
} 
                        

where the message member is a language-sensitive error message associated with the particular system exception.

Here is a list of Xaraya System Exceptions:

UNKNOWN: indicates that something (unknown) was wrong
ID_NOT_EXIST: indicates that the identifier you provided is associated with no
existing object

BAD_PARAM: indicates that you are passing a bad parameter
DATABASE_ERROR: indicates a database operation failure
NO_PERMISSION: indicates that you don't have right permission to accede to a
particular resource (note that system exception is not raised from xarSecAuthAction API but from other functions in which xarSecAuthAction is called)

MODULE_NOT_EXIST:
MODULE_FILE_NOT_EXIST:
MODULE_FUNC_NOT_EXIST:

TBD: extend this list

3.2 Xaraya API changes

Here is a list of modifications that should occur on current version of Xaraya API. Every modification exposed here is described by three fields:

api: the name of API function
changes: the modifications that will occur
exceptions: the exceptions that modified API function will raise (note that throwed back exceptions are excluded from this list)

api: xarConfigGetVar changes: no changes on return value, add code to raise exceptions exceptions: ID_NOT_EXIST, DATABASE_ERROR

api: xarConfigSetVar changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarConfigDelVar changes: to be done

api: xarDBGetConn changes: no changes

api: xarDBGetTables changes: no changes

api: xarVarCleanFromInput changes: no changes on return value, add code to raise exceptions exceptions: ID_NOT_EXIST

api: xarVarPrepForDisplay changes: no changes

api: xarVarPrepHTMLDisplay changes: no changes, add code to throw back exceptions

api: xarVarPrepForStore changes: no changes

api: xarVarPrepForOS changes: no changes

api: xarVarCensor changes: no changes, add code to throw back exceptions

api: xarVarValidate changes: no changes

api: xarGetBaseURI changes: no changes

api: xarGetBaseURL changes: no changes

api: xarRedirect changes: no changes

api: xarBlockShow changes: no changes, add code to throw back exceptions

api: xarBlockLoad changes: no changes, add code to throw back exceptions

api: xarBlockGetInfo changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarModGetVar changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarModSetVar changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarModDelVar changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarModGetIDFromName changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarModGetInfo changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarModGetUserMods changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarModGetAdminMods changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarModAPILoad changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM, MODULE_NOT_EXIST, MODULE_FILE_NOT_EXIST

api: xarModDBInfoLoad changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM, MODULE_NOT_EXIST

api: xarModLoad changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM, MODULE_NOT_EXIST, MODULE_FILE_NOT_EXIST

api: xarModAPIFunc changes: change to return void on error, add code to raise exceptions exceptions: BAD_PARAM, MODULE_FUNC_NOT_EXIST

api: xarModFunc changes: change to return void on error, add code to raise exceptions exceptions: BAD_PARAM, MODULE_FUNC_NOT_EXIST

api: xarModURL changes: change to return void on error, add code to raise exceptions exceptions: BAD_PARAM

api: xarModAvailable changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarModGetName changes: to be done

api: xarModRegisterHook changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarModUnregisterHook changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarModCallHooks changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarSecAddSchema changes: no changes

api: xarSecAuthAction changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarSecGetAuthInfo changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarSecGetLevel changes: no changes

api: xarSecGenAuthKey changes: no changes

api: xarSecConfirmAuthKey changes: no changes

api: xarSessionGetVar changes: no changes

api: xarSessionSetVar changes: no changes

api: xarSessionDelVar changes: no changes

api: xarUserLogIn changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR, BAD_PARAM

api: xarUserLogOut changes: change to return void on error, add code to raise exceptions exceptions: DATABASE_ERROR

api: xarUserLoggedIn changes: no changes

api: xarUserGetTheme changes: no changes

api: xarUserGetLang changes: no changes

api: xarUserGetVar changes: change to return void on error, add code to raise exceptions exceptions: BAD_PARAM, ID_NOT_EXIST, NO_PERMISSION

api: xarUserSetVar changes: change to return void on error, add code to raise exceptions exceptions: BAD_PARAM, ID_NOT_EXIST, NO_PERMISSION

api: xarUserValidateVar changes: change to return void on error, add code to raise exceptions exceptions: BAD_PARAM, ID_NOT_EXIST

3.3 Changelog

0.1 (May 8, 2002)

Extended Xaraya System Exceptions section.

Added Xaraya API changes section.

pre-0.1 (May 5, 2002)

Initial Version by Marco Canini <marco.canini@postnuke.com>