Exceptions
Definition​
Exceptions are classes the handles errors, and helps developers debug their code in a more efficient way.
Principles​
- Exceptions can be thrown from anywhere in the application.
- Exceptions SHOULD be created inside the Containers. However, general Exceptions CAN be created in the
Shiplayer.
Rules​
- All Exceptions MUST extend
App\Ship\Parents\Exceptions\Exception. - Shared (general) Exceptions between all Containers SHOULD be created in the Exceptions Ship folder (
app/Ship/Exceptions/*). - Every Exception SHOULD have two properties
httpStatusCodeandmessage, both properties will be displayed when an error occurs. You can override those values while throwing the error.
Folder Structure​
- App
- Containers
- {container-name}
- Exceptions
- AccountFailedException.php
- ...
- Ship
- Exceptions
- IncorrectIdException.php
- InternalErrorException.php
- ...
Code Samples​
User Exception:
<?php
namespace App\Containers\User\Exceptions;
use App\Ship\Parents\Exceptions\Exception;
use Symfony\Component\HttpFoundation\Response;
class AccountFailedException extends Exception
{
public $httpStatusCode = Response::HTTP_CONFLICT;
public $message = 'Failed creating new User.';
public $code = 4711;
}
General Exception:
<?php
namespace App\Ship\Exceptions;
use App\Ship\Parents\Exceptions\Exception;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
class InternalErrorException extends Exception
{
public $httpStatusCode = SymfonyResponse::HTTP_INTERNAL_SERVER_ERROR;
public $message = 'Something went wrong!';
}
General Exception with CustomData:
<?php
namespace App\Ship\Exceptions;
use App\Ship\Parents\Exceptions\Exception;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
class AwesomeExceptionWithCustomData extends Exception
{
public $httpStatusCode = SymfonyResponse::HTTP_INTERNAL_SERVER_ERROR;
public $message = 'Something went wrong!';
public $code = 1234;
/*
* Everything you add here will be automatically added to the ExceptionFormatter on the top level!
* You can define any structure you want or maybe include translated messages
*/
public function addCustomData() {
return [
'title' => 'nice',
'description' => 'one fancy description here',
'foo' => true,
'meta' => [
'bar' => 1234,
]
];
}
}
Exception usage from anywhere:
<?php
throw new AccountFailedException();
Usage with Log for Debugging:
<?php
throw (new AccountFailedException())->debug($e); // debug() accepts string or \Exception instance
Usage and overriding the default message:
<?php
throw new AccountFailedException('I am the message to be displayed for the user');
Usage and overwriting pre-set CustomData
<?php
throw (new AwesomeExceptionWithCustomData())->overrideCustomData(['foo' => 'bar']);
Application Error Codes​
Apiato provides a convenient way to manage all application error codes in one central place. Therefore, Apiato provides, amongst others, the \App\Ship\Exceptions\Codes\ApplicationErrorCodesTable class, which already holds various information for multiple errors.
Thereby, one error look like this:
const BASE_GENERAL_ERROR = [
'code' => 1001,
'title' => 'Unknown / Unspecified Error.',
'description' => 'Something unexpected happened.',
];
Note that the code is used to be sent back to the client. The title and description, however, can be used to automatically generate a documentation regarding all defined error codes and their meaning. Please note that this feature is currently not implemented but will be added later on.
Linking Exceptions and Error Codes​
In order to link an error code to an Exception, you simply need override the useErrorCode() method of the Exception.
Consider the following example:
class InternalErrorException extends Exception
{
public $httpStatusCode = SymfonyResponse::HTTP_INTERNAL_SERVER_ERROR;
public $message = 'Something went wrong!';
public code = 4711; // this code will be overwritten by the useErrorCode() method!
public function useErrorCode()
{
return ApplicationErrorCodes::BASE_INTERNAL_ERROR;
}
}
Please note that already defined $code values may be overwritten by the useErrorCode() method! Furthermore, this feature is completely optional - you may still use the known public $code = 4711; approach to manually set an error code.
Defining Own Error Code Tables​
Of course, Apiato allows you to define your own CustomErrorCodesTable. In fact, there already exists such a file where you can define your own error codes. Please note that the ApplicationErrorCodesTable may be adapted by Apiato - the others will not.
If you like to split the errors in various files, you can easily create a UserErrorCodesTable in respective namespace and define the errors accordingly. However, you need to manually "register" this code table. This can be achieved in the ErrorCodeManager::getCodeTables() method.
Now you can easily use your UserErrorCodesTable::USER_NOT_VERIFIED error in your Exception class.