Skip to content

Commit c6554ec

Browse files
Merge pull request #148 from MarcinOrlowski/dev
v8.0.0
2 parents 51c11d8 + 7cb838d commit c6554ec

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1279
-1765
lines changed

CHANGES.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ See [compatibility docs](docs/compatibility.md) for details about backward compa
66

77
## CHANGE LOG ##
88

9+
* v8.0.0 (2020-07-14)
10+
* **BACKWARD INCOMPATIBLE CHANGES** ([more info](docs/compatibility.md))
11+
* Improved performance by using calls qualified references.
12+
* [RB-132] Reworked exception handler helper to support delegated handlers for better flexibility.
13+
* Reverted depreciation of `BaseApiCodes` reserved range codes.
14+
* Sealed built-in data converter classes.
15+
* Removed `ResponseBuilderLegacy` class from the package.
16+
* Added German localization.
17+
918
* v7.1.2 (2020-07-12)
1019
* [RB-141] Fixed `JsonSerializableConverter` to deal non-string return data (reported by Jonatan Fekete)
1120

@@ -37,14 +46,14 @@ See [compatibility docs](docs/compatibility.md) for details about backward compa
3746
and all related stuff, incl. localization key `http_not_found`, configuration is now replace with more
3847
flexible generic code that provides error messages for all supported HTTP codes from in range `400-599`.
3948
* Added support for external data converters (related part of config changed too).
40-
* Config key `classes` is now (partially) `converter`. Its `method` key is gone and `handler`.
49+
* Config key `classes` is now (partially) `converter`. Its `method` key is gone and `handler` is used instead.
4150
needs to be added now, pointing to the class implementing `ConverterContract` acting as delegate worker.
4251
* Data converter now handles objects implementing `JsonSerializable` and `Arrayable` contracts as well.
4352

4453
* v6.3.2 (2019-11-07)
4554
* Added `ResponseBuilder::successWithMessage()` method.
4655
* Entries in `classes` config array can now have `pri` (default 0) to enforce order while
47-
merging config with built-in configuration.
56+
merging config with a built-in configuration.
4857
* Persian translation (Thanks to @FaridAghili).
4958
* Added Laravel 6.5 to Travis-CI unit tests.
5059

@@ -114,7 +123,7 @@ See [compatibility docs](docs/compatibility.md) for details about backward compa
114123
* `ResponseBuilder::errorWithDataAndHttpCode()` accepts now `null` as http code.
115124
* `ResponseBuilder::errorWithHttpCode()` accepts now `null` as http code.
116125
* Fixed `ExceptionHandlerHelper` replacing HTTP codes above 499 with 400.
117-
* Changed default built-in message for `HTTP_NOT_FOUND` error.
126+
* Changed default message for `HTTP_NOT_FOUND` error.
118127
* `ExceptionHandler` now falls back to `EX_UNCAUGHT_EXCEPTION` for all the cases.
119128
* Simplified `ExceptionHandlerHelperTest::testRender_HttpException()` test.
120129
* Removed `exception_handler.use_exception_message_first` feature.

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
## Introduction ##
3838

39-
`ResponseBuilder` is [Laravel](https://laravel.com/)'s helper designed to build nice, normalized and easy to consume REST API
39+
`ResponseBuilder` is a [Laravel](https://laravel.com/) helper designed to build nice, normalized and easy to consume REST API
4040
JSON responses.
4141

4242
## Benefits ##
@@ -52,7 +52,7 @@
5252
Android developers can use [ApiResponse](https://github.com/MarcinOrlowski/ApiResponse) library to handle `ResponseBuilder`
5353
responses produced in their mobile applications.
5454

55-
You are even covered in case of emergency as provided Exception Handler ensures your API keeps talking JSON (and
55+
You are even covered in a case of emergency as provided Exception Handler ensures your API keeps talking JSON (and
5656
not HTML) to its clients if case of any unexpected and unhandled exception.
5757

5858
Did I mention, you also get testing traits that would automatically cover your whole `ResponseBuilder` related code with
@@ -74,11 +74,11 @@
7474
"data": null
7575
}
7676

77-
Something went wrong? Just do:
77+
Something went wrong? Just type:
7878

7979
return ResponseBuilder::error(250);
8080

81-
and the following JSON response will be returned
81+
The following JSON response will then be returned:
8282

8383
{
8484
"success": false,
@@ -110,4 +110,3 @@
110110

111111
* Written and copyrighted &copy;2016-2020 by Marcin Orlowski <mail (#) marcinorlowski (.) com>
112112
* ResponseBuilder is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
113-

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "marcin-orlowski/laravel-api-response-builder",
33
"description": "Helps building nice, normalized and easy to consume Laravel REST API.",
44
"homepage": "https://github.com/MarcinOrlowski/laravel-api-response-builder",
5-
"version": "7.1.2",
5+
"version": "8.0.0",
66
"keywords": [
77
"laravel",
88
"json",

config/response_builder.php

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060

6161
/*
6262
|-----------------------------------------------------------------------------------------------------------
63-
| Converters for generic classes should use lower priority to allow dedicated converters to be used.
63+
| Generic converters should have lower pri to allow dedicated ones to kick in first when class matches
6464
|-----------------------------------------------------------------------------------------------------------
6565
*/
6666
\JsonSerializable::class => [
@@ -83,51 +83,67 @@
8383
|
8484
*/
8585
'exception_handler' => [
86-
/*
87-
* The following options can be used for each entry specified:
88-
* `api_code` : (int) mandatory api_code to be used for given exception
89-
* `http_code` : (int) optional HTTP code. If not specified, exception's HTTP status code will be used.
90-
* `msg_key` : (string) optional localization string key (ie. 'app.my_error_string') which will be used
91-
* if exception's message is empty. If `msg_key` is not provided, ExceptionHandler will
92-
* fall back to built-in message.
93-
* `msg_enforce`: (boolean) if `true`, then fallback message (either one specified with `msg_key`, or
94-
* built-in one will **always** be used, ignoring exception's message string completely.
95-
* If set to `false` (default) then it will enforce either built-in message (if no
96-
* `msg_key` is set, or message referenced by `msg_key` completely ignoring exception
97-
* message ($ex->getMessage()).
98-
*/
99-
'map' => [
100-
/*
101-
* HTTP Exceptions
102-
* ---------------
103-
* Configure how you want Http Exception to be handled based on its Http status code.
104-
* For each code you need to define at least the `api_code` to be returned in final response.
105-
* Additionally, you can specify `http_code` to be any valid 400-599 HTTP status code, otherwise
106-
* code set in the exception will be used.
107-
*/
108-
// HttpException::class => [
109-
// // used by unauthenticated() to obtain api and http code for the exception
110-
// HttpResponse::HTTP_UNAUTHORIZED => [
111-
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_UNATHORIZED_EXCEPTION,
112-
// ],
113-
// // Required by ValidationException handler
114-
// HttpResponse::HTTP_UNPROCESSABLE_ENTITY => [
115-
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_VALIDATION_EXCEPTION,
116-
// ],
117-
// // default handler is mandatory and MUST have both `api_code` and `http_code` set.
118-
// 'default' => [
119-
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_GENERIC_HTTP_EXCEPTION,
120-
// 'http_code' => HttpResponse::HTTP_BAD_REQUEST,
121-
// ],
122-
// ],
123-
// // This is final exception handler. If ex is not dealt with yet this is its last stop.
124-
// // default handler is mandatory and MUST have both `api_code` and `http_code` set.
125-
// 'default' => [
126-
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_UNHANDLED_EXCEPTION,
127-
// 'http_code' => HttpResponse::HTTP_INTERNAL_SERVER_ERROR,
128-
// ],
129-
// ],
130-
],
86+
/*
87+
* The following keys are supported for each handler specified.
88+
* `handler`
89+
* `pri`
90+
* `config`
91+
*
92+
* The following keys are supported in "config" entry for each handler specified:
93+
* `api_code` : (int) mandatory api_code to be used for given exception
94+
* `http_code` : (int) optional HTTP code. If not specified, exception's HTTP status code will be used.
95+
* `msg_key` : (string) optional localization string key (ie. 'app.my_error_string') which will be used
96+
* if exception's message is empty. If `msg_key` is not provided, ExceptionHandler will
97+
* fall back to built-in message, with message key built as "http_XXX" where XXX is
98+
* HTTP code used to handle given the exception.
99+
* `msg_enforce`: (boolean) if `true`, then fallback message (either one specified with `msg_key`, or
100+
* built-in one will **always** be used, ignoring exception's message string completely.
101+
* If set to `false` (default) then it will enforce either built-in message (if no
102+
* `msg_key` is set, or message referenced by `msg_key` completely ignoring exception
103+
* message ($ex->getMessage()).
104+
*/
105+
106+
\Illuminate\Validation\ValidationException::class => [
107+
'handler' => \MarcinOrlowski\ResponseBuilder\ExceptionHandlers\ValidationExceptionHandler::class,
108+
'pri' => -100,
109+
'config' => [
110+
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_VALIDATION_EXCEPTION,
111+
// 'http_code' => HttpResponse::HTTP_UNPROCESSABLE_ENTITY,
112+
],
113+
],
114+
115+
\Symfony\Component\HttpKernel\Exception\HttpException::class => [
116+
'handler' => \MarcinOrlowski\ResponseBuilder\ExceptionHandlers\HttpExceptionHandler::class,
117+
'pri' => -100,
118+
'config' => [
119+
// HttpException::class => [
120+
// // used by unauthenticated() to obtain api and http code for the exception
121+
// HttpResponse::HTTP_UNAUTHORIZED => [
122+
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_UNATHORIZED_EXCEPTION,
123+
// ],
124+
// // Required by ValidationException handler
125+
// HttpResponse::HTTP_UNPROCESSABLE_ENTITY => [
126+
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_VALIDATION_EXCEPTION,
127+
// ],
128+
// // default handler is mandatory and MUST have both `api_code` and `http_code` set.
129+
// 'default' => [
130+
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_GENERIC_HTTP_EXCEPTION,
131+
// 'http_code' => HttpResponse::HTTP_BAD_REQUEST,
132+
// ],
133+
// ],
134+
],
135+
// // This is final exception handler. If ex is not dealt with yet this is its last stop.
136+
// default handler is mandatory and MUST have both `api_code` and `http_code` set.
137+
138+
'default' => [
139+
'handler' => \MarcinOrlowski\ResponseBuilder\ExceptionHandlers\HttpExceptionHandler::class,
140+
'pri' => -127,
141+
'config' => [
142+
// 'api_code' => ApiCodes::YOUR_API_CODE_FOR_UNHANDLED_EXCEPTION,
143+
// 'http_code' => HttpResponse::HTTP_INTERNAL_SERVER_ERROR,
144+
],
145+
],
146+
],
131147
],
132148

133149
/*

docs/compatibility.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
# REST API Response Builder for Laravel #
44

5+
### v8 ###
6+
7+
* `[BREAKING]` Due to introduction of exception handlers, `ExceptionHandler` configuration has been changed.
8+
See [configuration docs](config.md) for more information.
9+
* `[Very Low]` Removed `ResponseBuilderLegacy` class from the package.
10+
11+
512
### v7 ###
613

714
* `[BREAKING]` As the library API migrated to Builder type of implementation, all the former API methods are now removed from

docs/config.md

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@
2424

2525
## classes ##
2626

27-
`Response Builder` can auto-convert to be used as response `data`. The following classes are supported out of the
28-
box:
27+
`Response Builder` can auto-convert to be used as response `data`. The following classes are supported out of the
28+
box:
2929

3030
* `\Illuminate\Database\Eloquent\Model`
3131
* `\Illuminate\Support\Collection`
3232
* `\Illuminate\Database\Eloquent\Collection`
3333
* `\Illuminate\Http\Resources\Json\JsonResource`
3434

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

3737
```php
3838
'converter' => [
@@ -41,20 +41,20 @@ Create new entry for each class you want to have supported. The entry key is a f
4141
'key' => 'items',
4242

4343
// Optional paramters
44-
'pri' => 0,
45-
],
44+
'pri' => 0,
45+
],
4646
],
4747
```
48-
The `handler` is full name of the class that implements `ConverterContract`. Object of that class will be instantiated
49-
and conversion method will be invked. The `key` is a string that will be used as the JSON response as key to array representation.
48+
The `handler` is full name of the class that implements `ConverterContract`. Object of that class will be instantiated
49+
and conversion method will be invked. The `key` is a string that will be used as the JSON response as key to array representation.
5050

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

57-
See [Data Conversion](docs.md#data-conversion) docs for closer details wih examples.
57+
See [Data Conversion](docs.md#data-conversion) docs for closer details wih examples.
5858

5959
## debug ##
6060

@@ -117,20 +117,42 @@ See [Data Conversion](docs.md#data-conversion) docs for closer details wih examp
117117
information. In such case you may want to assign separate API code to each of these "special" exceptions
118118
and this is where `exception_handler` section comes in.
119119

120-
Each configuration entry consits of exception class name as a key and parameters array with fields
121-
`api_code` and `http_code`. At runtime, exception handler will look for config entry for particualr
122-
exception class and if there's one, proper handler, dedicated to that exception class, kicks in
123-
and deals with the exception. If no such config exists, `default` handler will be used.
124-
125-
**NOTE:** For now there's no option to specify custom converted as of yet (but that's next step anywya),
126-
so adding own classes to the config same way we did for
127-
`\Symfony\Component\HttpKernel\Exception\HttpException::class` won't work.
120+
`ResponseBuilder` delegates handling of exceptions to dedicated handlers which lets you add your own
121+
when needed. Each configuration entry consits of name of the handler, its priority (which is useful if you
122+
deal with inherited exception classes) and optional configuration (depending on the handler):
123+
124+
```php
125+
'exception_handler' => [
126+
\Symfony\Component\HttpKernel\Exception\HttpException::class => [
127+
'handler' => \MarcinOrlowski\ResponseBuilder\ExceptionHandlers\HttpExceptionHandler::class,
128+
'pri' => -100,
129+
'config' => [
130+
HttpException::class => [
131+
// used by unauthenticated() to obtain api and http code for the exception
132+
HttpResponse::HTTP_UNAUTHORIZED => [
133+
'api_code' => ApiCodes::YOUR_API_CODE_FOR_UNATHORIZED_EXCEPTION,
134+
],
135+
// default handler is mandatory and MUST have both `api_code` and `http_code` set.
136+
'default' => [
137+
'api_code' => ApiCodes::YOUR_API_CODE_FOR_GENERIC_HTTP_EXCEPTION,
138+
'http_code' => HttpResponse::HTTP_BAD_REQUEST,
139+
],
140+
],
141+
],
142+
],
143+
],
144+
```
145+
146+
147+
At runtime, exception handler will look for config entry for particualr exception class and use dedicated handler if found. If
148+
no exact match exists, it will try to match the handler using `instanceof` and eventually faill back to default handler
149+
as specified in (mandatory) `default` config node.
128150

129151
## map ##
130152

131-
`ResponseBuilder` can automatically use text error message associated with error code and return in the
132-
response, once its configured to know which string to use for which code. `ResponseBuilder` uses standard
133-
Laravel's `Lang` facade to process strings.
153+
`ResponseBuilder` can automatically use text error message associated with error code and return in the
154+
response, once its configured to know which string to use for which code. `ResponseBuilder` uses standard
155+
Laravel's `Lang` facade to process strings.
134156

135157
```php
136158
'map' => [
@@ -139,7 +161,7 @@ Laravel's `Lang` facade to process strings.
139161
],
140162
```
141163

142-
See [Exception Handling with Response Builder](docs/exceptions.md) if you want to provide own messages for built-in codes.
164+
See [Exception Handling with Response Builder](docs/exceptions.md) if you want to provide own messages for built-in codes.
143165

144166
## min_code ##
145167

docs/docs.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,17 @@ return ResponseBuilder::asSuccess()
124124
->build();
125125
```
126126

127-
For simplicity of use, it's recommended to add the following `use` to your code (you can also use
128-
[namespace aliasing](https://www.php.net/manual/en/language.namespaces.importing.php)):
127+
For simplicity of use, it's recommended to add the following `use` to your code:
129128

130129
use MarcinOrlowski\ResponseBuilder\ResponseBuilder;
131130

132131
If you dislike typing `ResponseBuilder` you can use [namespace aliasing](https://www.php.net/manual/en/language.namespaces.importing.php):
132+
133+
use MarcinOrlowski\ResponseBuilder\ResponseBuilder as RB;
134+
135+
Then use short form in your code:
136+
137+
return RB::success();
133138

134139
Builder static methods:
135140

@@ -232,7 +237,7 @@ return ResponseBuilder::success($flights);
232237
],
233238
```
234239

235-
where parameters mean:
240+
Meaning of parameters:
236241

237242
* `handler` (mandatory) specifies class name that implements `ConverterContract` interface that is capable of doing the
238243
conversion of object of given class.
@@ -480,8 +485,8 @@ return MyResponseBuilder::errorWithData(ApiCode::SOMETHING_WENT_WRONG, $data);
480485

481486
### Overriding code to message conversion ###
482487

483-
`ResponseBuilder` automatically provides human readable error messages for each API code used but if for any
484-
reason you want to take control on this, you can now provide own implementation of `ResponseBuilder::getMessageForApiCode()`.
488+
`ResponseBuilder` automatically provides human readable error messages for each API code used but if for any
489+
reason you want to take control on this, you can now provide own implementation of `ResponseBuilder::getMessageForApiCode()`.
485490

486491
```php
487492
<?php
@@ -497,8 +502,7 @@ class MyResponseBuilder extends MarcinOrlowski\ResponseBuilder\ResponseBuilder
497502
}
498503
```
499504

500-
Please see current implementation for `getMessageForApiCode()` for details how to correctly obtain localization string key etc.
501-
505+
Please see current implementation for `getMessageForApiCode()` for details how to correctly obtain localization string key etc.
502506

503507
----
504508

0 commit comments

Comments
 (0)