rfc:enhanced_error_handling

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:enhanced_error_handling [2009/12/27 19:22] – Added course of action kampfcasparrfc:enhanced_error_handling [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ====== Request for Comments: Enhanced Error Handling ====== ====== Request for Comments: Enhanced Error Handling ======
-  * Version: 0.1 +  * Version: 0.5 
-  * Date:    2009-12-27+  * Date:    2010-01-10
   * Author:  Hans-Peter Oeri <hp@oeri.ch>   * Author:  Hans-Peter Oeri <hp@oeri.ch>
-  * Status:  Drafting+  * Status:  Draft (Inactive)
   * First Published at: http://wiki.php.net/rfc/enhanced_error_handling   * First Published at: http://wiki.php.net/rfc/enhanced_error_handling
  
 ===== Introduction ===== ===== Introduction =====
  
-php_error(), zend_throw_extension(), the @-operator... PHP and/or the Zend Engine respectively offer a variety of error issuance and handling mechanisms. There is, however, no encompassing concepts: Core functions only issue php_errors (suppressable), intl 1.0.3 by default suppresses all errors but can activate php_errors, pdo however has a proprietary flag to define error behaviour that allows exceptions - but limits php_error to E_WARNING.+php_error(), zend_throw_exception(), the @-operator... PHP and/or the Zend Engine respectively offer a variety of error issuance and handling mechanisms. There is, however, no encompassing concepts: Core functions only issue php_errors (suppressable), intl 1.0.3 by default suppresses all errors but can activate php_errors, pdo however has a flag to define error behaviour that allows exceptions - but limits php_error to E_WARNING. Furthermore, each extension has a different way of changing its error behaviour etc. etc.
  
-state that error handling has to be in the hands of the user (php coder). Some may prefer php_error()s, others prefer exceptions; some are ok with E_WARNINGs that indicate severe situations, others prefer E_ERROR for those cases; and some might want to either suppress all messages or default to a big exception block per script in production systems.+think that error behaviour has to be in the hands of the user (php coder). Different users have different preferences - and prefer different behaviour in different situations.
  
-===== Scope =====+==== Scope ====
  
 Error conditions are encountered in a variety of places and cases. This RFC only covers error conditions in a running script, e.g. a file was not found. Error conditions are encountered in a variety of places and cases. This RFC only covers error conditions in a running script, e.g. a file was not found.
  
 All other situations - like compilation problems, core errors in engine startup/shutdown - are out of scope. All other situations - like compilation problems, core errors in engine startup/shutdown - are out of scope.
 +
 +==== Differences Observed ====
 +
 +  * Almost all error behaviours include a human readable //error message// and a machine readable //error code//; the 'original' zend_error however, does not define error codes, but far less granular //error types// (which are nevertheless named errno in parts of the docs, e.g. set_error_handler).
 +  * Error codes - if used - do not follow any //common semantic rules// and are therefore not interpretable without knowing their source; even more, they might be defined externally (SQLSTATE or linked library).
 +  * While traditionally error numbers have mostly been numeric, also //alphanumeric// variants exist (SQLSTATE).
 +  * Error codes and - to a lesser extent - error messages are traditionally held in a special variable or place for later inspection. Information held there may be reset //upon request/new error// (errno in C, error_get_last in PHP) or with any subsequent //successful action/call// (PDO, intl).
 +  * There may be just a //single holding space// for later inspection of error information (error_get_last), a a //compartementalized// holding space for independent error information (PDO vs. PDOStatement) or even a //hierarchical// one, which combines the earlier two (intl).
 +  * Functions not bailing out on error situations should return a //defined error value//. There is, however, a  variety of defined error values - also dependent on the required valid return value range, which might include values that other functions use as error indicating value.
 +  * Definition of error actions - as described in the introduction - is handled by //php.ini// or //object calls// or //not available// at all. None of it offers all options.
 +
 +
 +===== Goals =====
 +
 +The goal would be to create a framework in which
 +  * the //PHP user// decides, what kind of error reaction he wishes; that includes
 +  * having a single //error call// that abstracts away from zend_errors/exceptions and
 +  * a minimal //inheritance of error behaviours//, such that different extensions and/or resource objects might be configured to react differently.
 +  * offers a //C-level API// for compiled extensions as well as a //PHP-level API// for frameworks in that language.
 +  * can be used in //OOP// as well as //non-OOP// situations.
 +
 +
 +Such goals can only be achieved under the side condition of //complete backwards compatibility//. Default behaviour of
 +existing php and extensions must not be changed - all existing error behaviour must be mappable.
  
 ===== Definitions ===== ===== Definitions =====
  
-==== Error Behaviours ====+==== Error Actions ====
  
 If an error condition is met, different types of reactions are possible: If an error condition is met, different types of reactions are possible:
 ^ Name               ^ Description                              ^ ^ Name               ^ Description                              ^
 | Suppress           | Note down error and return an //error value//, e.g. false/NULL | | Suppress           | Note down error and return an //error value//, e.g. false/NULL |
 +| Monitor            | same as Suppress, but let a php monitor know - independent of error handling taken by user code|
 | Error              | same as Suppress, but issue a php_error as well | | Error              | same as Suppress, but issue a php_error as well |
 | Throw              | same as Suppress, but throw an exception as well | | Throw              | same as Suppress, but throw an exception as well |
  
-The error behaviour should be configurable by the user; preferably system-wide and +The error action should be configurable by the user. An extension should usually not differ from the user's wishes.
-overridable. An extension should not, however, decide to differ from the user's wishes.+
  
-In any case, there should be a method to get at the noted-down error information, e.g. +Noted-down error information, e.g. error code and message etc., would be available by a standardized API. 
-error code and message.+ 
 +==== Error Levels ==== 
 + 
 +Existing extensions use their error mechanisms not only to issue grave errors, but also to 
 +transport mere "warnings" to the user - much like a message transport. As this is pre-existing, 
 +both an //error// and a //warning// call should be supplied. The latter - ignoring all configuration - 
 +choosing Suppress or Monitor as appropraiate action.
  
 ==== Error Parameters ==== ==== Error Parameters ====
  
-php_error needs an E_* value to distinguish warnings and errors and the Throw behaviour+Different behaviours, ask for different additional parameters:  
 +zend_error needs an E_* value to distinguish warnings and errors and throwing an exception
 needs an exception class. needs an exception class.
  
-Defaults for those parameters should be configurable like the error behaviourThe extension +Default values for those parameters should be configurable like the error actionHowevermore specific 
-should however be ablewhile issuing an error, to set appropriate parameters if necessary. +values - like an BadFunctionCallException while testing parameters have to be definable with the 
- +error call itself.
-For extreme cases - like "one big exception block per script" - the default parameters +
-should be enforcable by the user's wishes.+
  
 ==== Error Container Hierarchy ==== ==== Error Container Hierarchy ====
  
-PHP lives of its extensibility. An extension can offer a whole bunch of different classes +PHP lives of its extensibility. Different extensions currently show different 
-that are related; take ''intl'' as an example. It could be interesting for the user +default error behaviours. It goes without saying, that error behaviour must 
-to differentiate his error reactions by object and/or extension.  +keep being configurable //by extension//.
-He could wish to let the whole of ''intl'' throw a PersonalIntlExceptionClass upon errors or +
-decide to switch to exceptions for a long block of translation calls (not testing each +
-and every result on its own) while he usually prefers E_ERRORS being issued.+
  
-The proposal therefore stands for three-level hierarchy:+As some extensions currently do, I propose to add layer of error 
 +configurability on //object level// (see e.g. PDO -> by PDO connection). They should 
 +default to the extension's behaviour, but be configurable differently.
  
-^ Level           ^ Description ^ +Without any hassle, //inheritance// could be implementedThe error configuration on 
-| Global          | Define behaviour and default parameters | +PDO connection could be inherited its PDOStatements.
-|                 | Could be used to force behaviour as well as parameterseg. in production | +
-| Field/Extension | Inherits from Global level | +
-|                 | Overrides behaviour and parameters for a "field", e.g. all i18n in intl.so| +
-| Object          | Inherits from Field level | +
-|                 | Overrides behaviour and parameters for single object | +
- +
-If any level enforces behaviour and/or parameters, the lower levels will not deviate.+
  
 ===== Special Cases ===== ===== Special Cases =====
Line 70: Line 91:
 ==== Enforced Exception class ==== ==== Enforced Exception class ====
  
-Each level could enforce the use of a specific exception class, e.g. PersonalIntlExceptionClass() for all of intl.so. While forcing such a common class does ease catching, some information a more specific class could provide is lost.+A lower hierarchy level could enforce the use of a specific exception class, e.g. PersonalIntlExceptionClass() for all of intl.so. While forcing such a common class does ease catching, some information a more specific class could provide is lost.
  
-As of PHP 5.3, the concept of exception chaining has been introduced, whereas a "previous" extension can be attached. In order to keep the previously lost information, the concrete exception class given upon issuing an error should be chained to the enforced class.+As of PHP 5.3, the concept of exception chaining has been introduced, whereas a "previous" exception can be attached. In order to keep the previously lost information, the concrete exception class given upon issuing an error should be chained to the enforced class.
  
 ==== Notices ==== ==== Notices ====
Line 85: Line 106:
  
 If possible, the operator should be limited to errors in the execution of scripts but "silence" thrown exceptions as well (like a "per object" Suppress above). It's functionality should be prohibited, if a certain behaviour is enforced. If possible, the operator should be limited to errors in the execution of scripts but "silence" thrown exceptions as well (like a "per object" Suppress above). It's functionality should be prohibited, if a certain behaviour is enforced.
 +
 +===== C API =====
 +
 +The following does not represent compilable code.
 +
 +==== Error Container ====
 +
 +The levels mentioned above would need a common container structure to hold error
 +configuration as well as "last error" information. The same construct can be hold
 +by extensions as well as objects.
 +
 +<code c>
 +  struct error_container {
 +    char *name;                         // identification, e.g. extension name
 +    error_container *parent;            // hierarchy: inherit parent's configuration
 +    error_container *delegate;          // hierarchy: "last" error is in a child from this one
 +
 +    error_action     action;            // error behaviour for this container
 +    long             level;             // default E_*
 +    zend_class_entry *exception;        // default exception class
 +
 +    error_incident incident;            // last error's information on this container's level
 +  }
 +</code>
 +
 +==== Error Function ====
 +
 +<code c>
 +  error_behaviour error_yell( error_container *container, long level, char *exception, long code, char *msg );
 +  error_behaviour error_yellf( error_container *container, long level, char *exception, long code, char *format, ... );
 +</code>
 +
 +Instead of writing explicit calls to zend_error or zend_exception_throw, this call abstracts away the
 +error behaviour. It does, however return the //actual// action initiated.
 +
 +As errors might be suppressed, after the use of error_yell a defined return value should be returned to PHP.
 +One //cannot// be sure that the engine will branch away into an error or exception handler.
 +
 +==== Utility functions ===
 +
 +Apart from the error issuing function, several utility functions are needed, e.g.:
 +  * Creation/Destruction of error containers
 +  * Setting/Resetting error behaviour of containers
 +  * Reading error incidents
 +  * Clearing error incidents
 +
 +The corresponding API depends too much on implementation detais to discuss those here.
 +
 +===== PHP API =====
 +
 +Apart from extensions in C, php code itself could use such unified error configuration as well.
 +Above mentioned error_yell function as well as utility functions to configure error actions and
 +read error information should be available.
 +
 +A standard ErrorClass - implementing an object
 +level error container plus standardized methods to access it - should be available:
 +
 +<code php>
 +  class ErrorClass {
 +    function __construct( $parent_container )
 +    function setErrorAction(...);
 +    function resetErrorAction();
 +    function yellError(...);
 +    function getLastError();
 +  }
 +</code>
 +
 +Of course, the internal ErrorClass could be used as base class for
 +extension classes as well.
 +
 +Error containers would be identified by:
 +  * NULL: global/highest hierarchy
 +  * string: extension-level container (e.g. in a hash)
 +  * ErrorClass: object-level container
 +
 +In order to allow PHP frameworks to depend on an "extension level" container,
 +such a string-identified container should be creatable on user level.
  
 ===== Backwards Compatibility ===== ===== Backwards Compatibility =====
Line 90: Line 188:
 ==== Extensions ==== ==== Extensions ====
  
-Extensions can keep backwards compatibility, if their current default behaviour is mapped to the above-mentioned Field level. Even special cases should be representable with the mentioned behaviours, parameters and enforcement.+Extensions can keep backwards compatibility, if their current default behaviour is mapped to the above-mentioned extension level. Even special cases should be representable with the mentioned actions, parameters and enforcement.
  
 ==== Core ==== ==== Core ====
  
-I would personally not touch the core, but it's error behaviour should be representable as well.+The core should probably only be touched if this proposal (or something analogous) is included in it...
  
 ===== Course of Action and Patch ===== ===== Course of Action and Patch =====
  
-  - An intl extension-level implementation is being created by kampfcaspar at https://saintcyr.oeri.ch/trac/php-intl/+  - Development: https://saintcyr.oeri.ch/trac/php-error/
   - Given enough feedback and operating experience, the enhanced error handling could be bundled in an "error extension"   - Given enough feedback and operating experience, the enhanced error handling could be bundled in an "error extension"
-  - Other extensions could user the "error extension"+  - Other extensions could use the "error extension"
  
 ===== Changelog ===== ===== Changelog =====
Line 106: Line 204:
 ^ Date        ^ Author      ^ Message                 ^ ^ Date        ^ Author      ^ Message                 ^
 | 2009-12-27  | kampfcaspar | Created Initial Version | | 2009-12-27  | kampfcaspar | Created Initial Version |
 +| 2009-12-28  | kampfcaspar | Added draft API         | 
 +| 2010-01-07  | kampfcaspar | Overhaul                | 
 +| 2010-01-10  | kampfcaspar | +Differences Observed   |
rfc/enhanced_error_handling.1261941748.txt.gz · Last modified: 2017/09/22 13:28 (external edit)