Skip to main content
Version: 9.x

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 Ship layer.

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 httpStatusCode and message, 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.