Skip to content

Latest commit

 

History

History
417 lines (340 loc) · 12.7 KB

config.md

File metadata and controls

417 lines (340 loc) · 12.7 KB

REST API Response Builder for Laravel

Configuration

« Documentation table of contents


Configuration file

At runtime ResponseBuilder looks for response_builder.php configuration file in your application config/ folder and falls back to defaults if no config file is found. Please see Installation docs for more info how to properly set up config file.

Configuration options

Available configuration options and its current default values listed in alphabetical order. Please note, that in majority of use cases it should be perfectly sufficient to just use defaults and only tune the config when needed.

converter

Response Builder can auto-convert data to be used as response data. It supports both primitives and objects of any classes that have corresponding converter configured.

classes

Create new entry for each class you want to have supported. The entry key is a full class name ( including namespace):

'converter' => [
    \Illuminate\Database\Eloquent\Model::class => [
        'handler' => \MarcinOrlowski\ResponseBuilder\Converters\ToArrayConverter::class,
        'key'     => 'items',
        'pri'     => 0,
    ],
    \Illuminate\Pagination\Paginator::class => [
        'handler' => \MarcinOrlowski\ResponseBuilder\Converters\ArrayableConverter::class,
        'key'     => null,  // SPECIAL CASE. READ BELOW!
        'pri'     => 0,
    ],
],

Meaning of parameters:

  • handler (mandatory) specifies a full name of the class implementing ConverterContract. Object of that class will be instantiated and conversion method invoked with object to convert passed as method argument.
  • key (mandatory), value can be a string or (in some special cases, NULL is also allowed).

IMPORTANT Object conversion works recursively! That makes some implications, when you i.e. convert object (say A) which when converted still returns other objects (say Bs). In such case once ResponseBuilder will also try to convert B so final JSON representation contain plain JSON structures. So when converting an object of a given class that is going to be returned directly as response payload (i.e. RB::success($collection);), the string given as key will be used in returned JSON as converted data key. The only case where you can have key set to NULL is when you are sure you are dealing i.e. collection of objects, so the collection object will be key-ed in the response (as per its class' configuration), but each element of that collection should be returned as plain JSON array. In other words, you can only have NULL key value if your objects are part of other structures. You cannot have it in main objects, because ResponseBuilder would not be able to construct valid JSON Object without the key.

   ...
"data": {
"given-key": {
[converted object data]
}
}
...
  • pri (optional) is an integer being entry's priority (default 0). Entries with higher values will be matched first. If you got one class extending another and you want to support both of them with separate configuration, then you must ensure child class has higher priority than it's parent class.

All configuration entries are assigned priority 0 which can be changed using pri key (integer). This value is used to sort the entries to ensure that matching order is preserved. Entries with higher priority are matched first etc. This is very useful when you want to indirect configuration for two classes where additionally second extends first one. So if you have class A and B that extends A and you want different handling for B than you have set for A then B related configuration must be set with higher priority.

IMPORTANT For each object ResponseBuilder checks if we have configuration entry matching exactly object class name. If no such mapping is found, then the whole configuration is walked again, but this time we take inheritance into consideration and use instanceof to see if we have a match, therefore you need to pay attention your config specifies lower priority (i.e. -10) for all the generic handlers. Doing that ensures any more specific handler will be checked first. If no handler is found for given object, the exception is thrown.

When you pass the array it will be walked recursively and the conversion will take place on all known elements as well:

$data = [
   'flight' = App\Flight::where(...)->first(),
   'planes' = App\Plane::where(...)->get(),
];

would produce the following response (contrary to the previous examples, source array keys are preserved):

{
  "flight": {
    "airline": "lot",
    "flight_number": "lo123",
    ...
  },
  "planes": [
    {
      "make": "airbus",
      "registration": "F-GUGJ",
      ...
    },
    {
      "make": "boeing",
      "registration": "VT-ANG",
      ...
    }
  ]
}

See Data Conversion docs for closer details wih examples.

NOTE In case of data conversion problems add RB_CONVERTER_DEBUG=true entry to your .env file (also see debug for related config options) then peek Laravel log to see what converter was used for each type of data and why it was choosen.

primitives

Starting from v9, ResponseBuilder suppors passing primitives as direct payload, removing the need of wrapping it in separate container (like array or object). The following primitives are supported:

  • array
  • boolean
  • double
  • integer
  • string

For each of these types there's configuration entry in primitives node of converter config. Each entry defined key which is an arbitrary string, used for given primitive. The default value for all supported primitives is value. For example, pre v9 would require

    RB::success(['value' => 12.25]);

while with v9+ if can be simplified:

    RB::success(12.25);

and both would yield the same result:

{
  "success": true,
  "code": 0,
  "locale": "en",
  "message": "OK",
  "data": {
    "value": 12.25
  }
}

data_always_object

Added in v9.3.0

By default, when no payload is to be returned (i.e. RB::success();), the data node of the JSON response would be returned with the value of NULL:

{
  "success": true,
  "code": 0,
  "locale": "en",
  "message": "OK",
  "data": null
}

When this option is set to TRUE, the data will be always valid JSON object, even if no data is to be returned. In such case the object will be returned empty:

{
  "success": true,
  "code": 0,
  "locale": "en",
  "message": "OK",
  "data": {}
}

debug

NOTE Do not use debug mode on production as it may expose i.e. your filesystem structure or class names or other internals that should not really be public.

'debug' => [
    'debug_key' => 'debug',

    'exception_handler' => [
           'trace_key' => 'trace',
           'trace_enabled' => env('APP_DEBUG', false),
    ],

    // Controls debugging features of payload converter class.
    'converter' => [
        // Set to true to figure out what converter is used for given data payload and why.
        'debug_enabled' => env('RB_CONVERTER_DEBUG', false),
    ],

],

debug_key - name of the JSON key trace data should be put under when in debug node. When ExceptionHandler kicks with debug mode enabled, returned JSON structure would contain additional debug data with information about class name, file name and line number:

{
  "success": false,
  "code": 0,
  "locale": "en",
  "message": "Uncaught Exception",
  "data": null,
  "debug": {
    "trace": {
      "class": "<EXCEPTION CLASS NAME>",
      "file": "<FILE THAT CAUSED EXCEPTION>",
      "line": "<LINE NUMBER>"
    }
  }
}

encoding_options

This option controls data JSON encoding. Since v3.1, encoding was relying on framework's defaults, however this caused valid UTF-8 characters (i.e. accents) to be returned escaped, which, while technically correct, and theoretically transparent) might not be desired.

To prevent escaping, add JSON_UNESCAPED_UNICODE:

JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_AMP|JSON_HEX_QUOT|JSON_UNESCAPED_UNICODE

Laravel's default value:

JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_AMP|JSON_HEX_QUOT

See json_encode() manual for more details.

exception_handler

ResponseBuilder's Exception handler helper is plug-and-play helper that will automatically handle any exception thrown by your code and expose valid JSON response to the client applications. But aside from error handling, some programmers use exceptions to quickly break the flow and return with additional information. In such case you may want to assign separate API code to each of these "special" exceptions and this is where exception_handler section comes in.

ResponseBuilder delegates handling of exceptions to dedicated handlers which lets you add your own when needed. Each configuration entry consits of name of the handler, its priority (which is useful if you deal with inherited exception classes) and optional configuration (depending on the handler):

'exception_handler' => [
    \Symfony\Component\HttpKernel\Exception\HttpException::class => [
        'handler' => \MarcinOrlowski\ResponseBuilder\ExceptionHandlers\HttpExceptionHandler::class,
        'pri'     => -100,
        'config'  => [
            HttpException::class => [
                // used by unauthenticated() to obtain api and http code for the exception
                HttpResponse::HTTP_UNAUTHORIZED => [
                    'api_code' => ApiCodes::YOUR_API_CODE_FOR_UNATHORIZED_EXCEPTION,
                ],
                // default handler is mandatory and MUST have both `api_code` and `http_code` set.
                'default' => [
                'api_code'  => ApiCodes::YOUR_API_CODE_FOR_GENERIC_HTTP_EXCEPTION,
                    'http_code' => HttpResponse::HTTP_BAD_REQUEST,
                ],
            ],
        ],
    ],
],

At runtime, exception handler will look for config entry for particualr exception class and use dedicated handler if found. If no exact match exists, it will try to match the handler using instanceof and eventually faill back to default handler as specified in (mandatory) default config node.

map

ResponseBuilder can automatically use text error message associated with error code and return in the response, once its configured to know which string to use for which code. ResponseBuilder uses standard Laravel's Lang facade to process strings.

'map' => [
    ApiCode::SOMETHING => 'api.something',
    ...
],

If given error code is not present in map, ResponseBuilder will provide fallback message automatically (default message is like "Error #xxx"). This means it's perfectly fine to have whole map array empty in your config, however you MUST have map key present nonetheless:

'map' => [],

Also, read Overriding built-in messages to see how to override built-in messages.

NOTE: Config file may grow in future so if you are not using defaults, then on package upgrades check CHANGES.md to see if there're new configuration options. If so, and you already have config published, then you need to look into dist config file in vendor/marcin-orlowski/laravel-api-response-builder/config/ folder and grab new version of config file.

See Exception Handling with Response Builder if you want to provide own messages for built-in codes.

min_code

This option defines lowest allowed (inclusive) code that can be used.

NOTE ResponseBuilder reserves first 19 codes for its own needs. First code you can use is 20th code in your pool.

'min_code' => 100,

max_code

Min api code in assigned for this module (inclusive). This option defines the highest allowed ( inclusive) code that can be used.

'max_code' => 1024,