8000 Add responses helper. · sablesoft/laravel-json-api@a8f2b9d · GitHub
[go: up one dir, main page]

Skip to content

Commit a8f2b9d

Browse files
committed
Add responses helper.
1 parent 1a719f8 commit a8f2b9d

File tree

7 files changed

+328
-19
lines changed

7 files changed

+328
-19
lines changed

README.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ For full information on the spec, plus examples, see http://jsonapi.org
1212

1313
## Features
1414

15-
@todo
15+
* Encoding of JSON API responses using the `neomerx/json-api` package.
16+
* Start JSON API support on route groups through a single piece of middleware, which automatically checks request headers and loads JSON API query parameters.
17+
* Registration of JSON API defined resource end-points via a simple route helper.
18+
* Define supported JSON API extensions via middleware (on route groups or individual controllers).
19+
* A JSON API controller providers helpers to:
20+
- Automatically check request query parameters.
21+
- Decode request body content into objects with a standard, fluent, interface. Makes handling content easier.
22+
- Validate request body content as it is being decoded, including using Laravel validates on resource object attributes.
23+
- Helpers for sending common JSON API responses, that automatically include requested encoding parameters, the encoded media type plus registered supported extensions.
24+
* Rendering of exceptions into JSON API error responses, plus easy sending of error responses via throwable JSON API error objects.
25+
* Configuration settings - including schemas, encoders, decoders and exception rendering - all defined in a configuration file in your Laravel application.
1626

1727
## Installation
1828

@@ -60,7 +70,7 @@ Route::group(['middleware' => M::JSON_API], function () {
6070
});
6171
```
6272

63-
If every route in your application is a JSON API endpoint, then you can set the `C::IS_GLOBAL` option to true. This will install the same piece of middleware on the HTTP Kernel, so that it is invoked for every request.
73+
If every route in your application is a JSON API endpoint, then you can set the `C::IS_GLOBAL` option to `true`. This will install the same piece of middleware on the HTTP Kernel, so that it is invoked for every request.
6474

6575
#### Defining Endpoints
6676

@@ -89,7 +99,7 @@ Per resource type, the following endpoints will be registered (using the `articl
8999
| /articles/:id/relationships/author | GET | `readAuthorRelationship($id)` |
90100
| /articles/:id/relationships/author | PATCH | `updateAuthorRelationship($id)` |
91101
| /articles/:id/comments | GET | `readComments($id)` |
92-
| /articles/:id/relationships/comments | GET | `readCommentRelationship($id)` |
102+
| /articles/:id/relationships/comments | GET | `readCommentsRelationship($id)` |
93103
| /articles/:id/relationships/comments | PATCH | `updateCommentsRelationship($id)` |
94104
| /articles/:id/relationships/comments | DELETE | `deleteCommentsRelationship($id)` |
95105

@@ -145,7 +155,7 @@ Note that if you are adding the trait to your own custom controller, you will ne
145155

146156
#### HTTP Content Body
147157

148-
To decode the request content body with the decoder that matched the request `Content-Type` header, then call `$this->getContentBody()`. If no decoder has matched the request header, calling this method will result in a `400 Bad Request` response to the client.
158+
To decode the request content body with the decoder that matched the request `Content-Type` header, then call `$this->getContentBody()`.
149159

150160
If you want to use a `CloudCreativity\JsonApi\Contracts\Object\DocumentInterface` object to handle the request content in your controller action, use `$this->getDocumentObject()`. This method ensures the decoder has returned a `DocumentInterface` object, or if it has returned a `stdClass` object it will be cast to a `DocumentInterface` object.
151161
Shorthands are also provided if you are expecting the document to contain a resource object in its data member, or if the provided document represents a relationship. Use `$this->getResourceObject()` and `$this->getRelationshipObject()` respectively.
@@ -218,6 +228,45 @@ These helper methods are provided by the `DocumentValidatorTrait`, which uses th
218228

219229
#### Responses
220230

231+
The class `CloudCreativity\JsonApi\Http\Responses\ResponsesHelper` provides a number of methods for constructing JSON API responses. This helper automatically uses request encoding parameters, the matched encoding media type plus any registered supported extensions.
232+
233+
If you have extended the `JsonApiController`, you can use this helper by calling `$this->reply()` then the method for the type of response you want to send. For example, to send a content response:
234+
235+
``` php
236+
class ArticlesController extends JsonApiController
237+
{
238+
// ...
239+
240+
public function read($id)
241+
{
242+
$article = Article::find($id);
243+
244+
if (!$article) {
245+
$this->notFound();
246+
}
247+
248+
return $this
249+
->reply()
250+
->content($article);
251+
}
252+
}
253+
```
254+
255+
The available helpers are:
256+
257+
| Method | Detail |
258+
| :----- | :----- |
259+
| `statusCode` | Send a status code only reply |
260+
| `noContent` | Send a no content reply (204) |
261+
| `meta` | Send meta only |
262+
| `content` | Send content (resource object, null, or collection) |
263+
| `created` | Send a resource created response (encoded object, location header and 201 status |
264+
| `relationship` | Send a relationship response (encoded identifier, null, or collection of identifiers) |
265+
266+
See the class for the parameters that each helper method accepts.
267+
268+
The reply method is added to the controller via the `ReplyTrait`.
269+
221270
### Exception Handling
222271

223272
To add JSON API support to your application's Exception Handler, add the `Exceptions\HandlerTrait` to your `App\Exceptions\Handler` instance. Then, in your `render()` method you can do the following:

src/Http/Controllers/DocumentDecoderTrait.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use JsonApi;
1313
use Neomerx\JsonApi\Contracts\Codec\CodecMatcherInterface;
1414
use Neomerx\JsonApi\Contracts\Decoder\DecoderInterface;
15-
use Neomerx\JsonApi\Contracts\Integration\ExceptionThrowerInterface;
1615
use RuntimeException;
1716

1817
/**
@@ -33,9 +32,7 @@ public function getContentBody(ValidatorInterface $validator = null)
3332
$decoder = $codecMatcher->getDecoder();
3433

3534
if (!$decoder instanceof DecoderInterface) {
36-
/** @var ExceptionThrowerInterface $thrower */
37-
$thrower = App::make(ExceptionThrowerInterface::class);
38-
$thrower->throwBadRequest();
35+
throw new RuntimeException('A decoder should be set by now. Are you in a JSON API route?');
3936
}
4037

4138
if ($validator && !$decoder instanceof ValidatorAwareInterface) {

src/Http/Controllers/DocumentValidatorTrait.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
namespace CloudCreativity\JsonApi\Http\Controllers;
44

5-
use CloudCreativity\JsonApi\Validator\Relationships\BelongsToValidator;
65
use CloudCreativity\JsonApi\Validator\Relationships\HasManyValidator;
6+
use CloudCreativity\JsonApi\Validator\Relationships\HasOneValidator;
77
use CloudCreativity\JsonApi\Validator\Resource\IlluminateResourceValidator;
88

99
/**
@@ -47,11 +47,11 @@ public function getResourceObjectValidator(
4747

4848
/**
4949
* @param string|string[]|null $expectedTypeOrTypes
50-
* @return BelongsToValidator
50+
* @return HasOneValidator
5151
*/
5252
public function getHasOneValidator($expectedTypeOrTypes = null)
5353
{
54-
return new BelongsToValidator($expectedTypeOrTypes);
54+
return new HasOneValidator($expectedTypeOrTypes);
5555
}
5656

5757
/**

src/Http/Controllers/JsonApiController.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
namespace CloudCreativity\JsonApi\Http\Controllers;
44

5-
use CloudCreativity\JsonApi\Error\ErrorException;
65
use CloudCreativity\JsonApi\Error\ThrowableError;
6+
use Illuminate\Http\Response;
77
use Illuminate\Routing\Controller;
8-
use Neomerx\JsonApi\Contracts\Document\ErrorInterface;
98

109
/**
1110
* Class JsonApiController
@@ -15,7 +14,8 @@ class JsonApiController extends Controller
1514
{
1615

1716
use QueryCheckerTrait,
18-
DocumentValidatorTrait;
17+
DocumentValidatorTrait,
18+
ReplyTrait;
1919

2020
/**
2121
* Whether query parameters should automatically be checked before the controller action method is invoked.
@@ -41,21 +41,32 @@ public function callAction($method, $parameters)
4141
/**
4242
* @param array $parameters
4343
* @return void
44-
* @throws ErrorInterface
44+
* @throws ThrowableError
4545
*/
4646
public function missingMethod($parameters = [])
4747
{
48-
throw new ThrowableError('Method Not Allowed', 405);
48+
throw new ThrowableError('Method Not Allowed', Response::HTTP_METHOD_NOT_ALLOWED);
4949
}
5050

5151
/**
5252
* @param string $method
5353
* @param array $parameters
5454
* @return void
55-
* @throws ErrorException
55+
* @throws ThrowableError
5656
*/
5757
public function __call($method, $parameters)
5858
{
59-
throw new ThrowableError('Not Implemented', 501);
59+
throw new ThrowableError('Not Implemented', Response::HTTP_NOT_IMPLEMENTED);
60+
}
61+
62+
/**
63+
* Helper method to throw a not found exception.
64+
*
65+
* @return void
66+
* @throws ThrowableError
67+
*/
68+
public function notFound()
69+
{
70+
throw new ThrowableError('Not Found', Response::HTTP_NOT_FOUND);
6071
}
6172
}

src/Http/Controllers/ReplyTrait.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace CloudCreativity\JsonApi\Http\Controllers;
4+
5+
use App;
6+
use CloudCreativity\JsonApi\Http\Responses\ResponsesHelper;
7+
8+
/**
9+
* Class ReplyTrait
10+
* @package CloudCreativity\JsonApi
11+
*/
12+
trait ReplyTrait
13+
{
14+
15+
/**
16+
* @return ResponsesHelper
17+
*/
18+
public function reply()
19+
{
20+
return App::make(ResponsesHelper::class);
21+
}
22+
}

0 commit comments

Comments
 (0)
0