-
Notifications
You must be signed in to change notification settings - Fork 2
Insulin Exception
#Insulin Exception
The Insulin_Exception is the base exception from which all others extend. It allows you to easily create and throw new exceptions, create easily recognisable and unique error codes, to configure multi-language exception messages, add previous exceptions and also has a custom method which creates a pretty-printable log-message string.
#How to
So, lets get hands on.
To create a new exception for a custom module 'MyModule', create the following file:
<?php
//modules/MyModule/exceptions/Exception.php
require_once 'Insulin/Exception.php';
class MyModule_Exception extends Insulin_Exception
{
}
Note that, according to the Insulin standards, a base exception should be create for MyModule, as done above. Furthermore, these standards also define that all custom module's exceptions should be placed under the 'modules/MyModule/exceptions' folder. As for core module customizations, the exceptions should be in 'custom/modules/module_name/exceptions' folder instead.
If, by instance, one needs to throw an exception when a record isn't found, the first thing to do is the creation of the module's base exception (which extends from Insulin_Exception), in other words, the exception from which all module's exceptions will extend from. After that, a specific exception should be created for the issue in question, in this case, the exception could be named IdNotFoundException where it would receive the record id related to the registry that wasn't found, in order for us to have a more meaningful exception message while debugging.
On to creating the new exception:
<?php
//modules/MyModule/exceptions/IdNotFoundException.php
require_once 'modules/MyModule/exceptions/Exception.php';
class MyModule_IdNotFoundException extends MyModule_Exception
{
public function __construct($id)
{
parent::__construct(array($id));
}
}
Now, you might be asking your self, why are we only passing the id? In the Insulin_Exception, the first argument of the constructor is an array with all the variables needed to have a more meaningful exception message; in the second argument, the previous exception (optional), that allows traceability between exceptions and an easier understanding of the origin of the exception caught.
And what about the error message? The Insulin_Exception, uses the SugarCRM label mechanism to provide multi-language support for its error messages. Error messages are searched for in the $mod_strings and $app_strings. The labels defined in the $mod_strings override the ones in the $app_strings. If the $app_strings are used, the Insulin standards define that the exception messages should be placed in "language_code.module_name.php" under '/custom/Extension/application/Ext/Language'. If, by instance, both English and Portuguese languages are supported, add the messages to:
- en_us.MyModule.php
- pt_PT.MyModule.php
What about the error code? Also, what key should be used to add the error message to the languages array? For the InsulinException these are the same, the exceptions error code should be used as a key of the array entry. The exceptions error code are automatically defined based on the exception class name. It is a string composed of uppercase words separated by underscores '_'. The keys are composed by separating with underscores the CamelCase words from the exception class name and then place all the text in uppercase. Thus, for the MyModule_IdNotFoundException you will get the code: 'MY_MODULE_ID_NOT_FOUND_EXCEPTION'.
Note that, exceptions with an uppercase letter followed by another uppercase letter, should not be separated by an underscore in the exception code, e.g, for a work orders module, named WO, in a IdNotFoundException it would get WO_ID_NOT_FOUND_EXCEPTION. But, if you have a module that starts with a lower case letter and is followed by an upper case letter/word, the exception code should have the the lower case letter separated by an '_', therefore in a ePortal module you would get E_PORTAL_ID_NOT_FOUND_EXCEPTION.
Here is a code sample:
$app_strings['MY_MODULE_ID_NOT_FOUND_EXCEPTION'] = "Could not find the record.";
The variables defined in the array passed as first argument of the class constructor, can be added to the exception's message by placing a token like "%1$s" (same as used in the php sprintf function, see http://php.net/sprintf), where the number is the position of the variable in the array. Knowing this, we can define a more precise and informative error message and the arguments can be used in any order:
$app_strings['MY_MODULE_ID_NOT_FOUND_EXCEPTION'] = "Could not find the record with id '%1\$s'.";
Can I instantiate the Insulin_Exception directly? Its not a good practice to do so, and it should only be done for "coding" exceptions. Nonetheless it is possible. For this, the error message should not be defined in the $app_strings, but pass it as the first entry of the arguments array. Like so:
require_once 'Insulin/Exception.php';
throw new Insulin_Exception(array(
'Some Insulin_Exception error message.'
));