Skip to content

Commit 18d997f

Browse files
committed
Add documentation about ItemDocumentBuilder, ItemHydrator and Repository classes [skip ci]
1 parent b8d1ae8 commit 18d997f

File tree

2 files changed

+142
-27
lines changed

2 files changed

+142
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This release includes changes to some interfaces. This is a breaking change if y
1111
### Added
1212

1313
* Added `OneRelationInterface` and `ManyRelationInterface` to differentiate between singular and plural relations.
14+
* Added documentation about `ItemDocumentBuilder`, `ItemHydrator` and `Repository` classes.
1415

1516
### Changed
1617

README.MD

Lines changed: 141 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ if ($document->hasErrors()) {
6565
}
6666
```
6767

68+
6869
## Configuration
6970

7071
The following is the default configuration provided by this package:
@@ -94,32 +95,6 @@ php artisan vendor:publish --provider="Swis\JsonApi\Client\Providers\ServiceProv
9495
```
9596

9697

97-
## Clients
98-
99-
This package offers two clients; `DocumentClient` and `Client`.
100-
101-
### DocumentClient
102-
103-
This is the client that you would generally use.
104-
Per the [JSON API spec](http://jsonapi.org/format/#document-structure), all requests and responses are documents.
105-
Therefore, this client always expects a `\Swis\JsonApi\Client\Interfaces\DocumentInterface` as input when posting data and always returns this same interface.
106-
This can be a plain `Document` when there is no data, an `ItemDocument` for an item, a `CollectionDocument` for a collection or an `InvalidResponseDocument` when the server responds with a non 2xx response.
107-
108-
The `DocumentClient` follows the following steps internally:
109-
1. Send the request using your HTTP client;
110-
2. Use [art4/json-api-client](https://github.com/art4/json-api-client) to parse and validate the response;
111-
3. Create the correct document instance;
112-
4. Hydrate every item by using the item model registered with the `TypeMapper` or a `\Swis\JsonApi\Client\Item` as fallback;
113-
5. Hydrate all relationships;
114-
6. Add meta data to the document such as [errors](http://jsonapi.org/format/#errors), [links](http://jsonapi.org/format/#document-links) and [meta](http://jsonapi.org/format/#document-meta).
115-
116-
### Client
117-
118-
This client is a more low level client and can be used, for example, for posting binary data such as images.
119-
It can take everything your request factory takes as input data and returns the 'raw' `\Psr\Http\Message\ResponseInterface` wrapped in a `\Swis\JsonApi\Client\Response`.
120-
It does not parse or validate the response or hydrate items!
121-
122-
12398
## Items
12499

125100
By default, all items are an instance of `\Swis\JsonApi\Client\Item`.
@@ -129,7 +104,6 @@ You can define your own models by extending `\Swis\JsonApi\Client\Item` or by im
129104
This can be useful if you want to define, for example, hidden attributes, casts or get/set mutators.
130105
If you use custom models, you must register them with the [TypeMapper](#typemapper).
131106

132-
133107
### Relations
134108

135109
On top of [jenssegers/model](https://github.com/jenssegers/model), this package has implemented [Laravel Eloquent-like relations](https://laravel.com/docs/eloquent-relationships).
@@ -201,6 +175,145 @@ class TypeMapperServiceProvider extends BaseTypeMapperServiceProvider
201175
```
202176

203177

178+
## Repository
179+
180+
For convenience, this package includes a basic repository with several methods to work with [resources](https://jsonapi.org/format/#document-resource-objects).
181+
You can create a repository for each of the endpoints you use based on `\Swis\JsonApi\Client\Repository`.
182+
This repository then uses standard CRUD endpoints for all its actions.
183+
184+
``` php
185+
class BlogRepository extends \Swis\JsonApi\Client\Repository
186+
{
187+
protected $endpoint = 'blogs';
188+
}
189+
```
190+
191+
If this repository (pattern) doesn't fit your needs, you can create your own implementation using the [clients](#clients) provided by this package.
192+
193+
## ItemDocumentBuilder
194+
195+
The `Repository` and `DocumentClient` require `ItemDocumentInterface` instances when creating or updating resources.
196+
Such documents can easily be created using the `ItemDocumentBuilder`.
197+
This builder takes an `ItemInterface` instance, usually created by the [TypeMapper](#typemapper), an array of attributes and optionally an id.
198+
Internally, it uses the [ItemHydrator](#itemhydrator) to hydrate the `ItemInterface` with the provided attributes before it creates the `ItemDocument`.
199+
200+
201+
## ItemHydrator
202+
203+
The `ItemHydrator` can be used to fill/hydrate an item and its relations using an associative array with attributes.
204+
This is useful if you would like to hydrate an item with POST data from your request:
205+
206+
``` php
207+
$typeMapper = app(Swis\JsonApi\Client\TypeMapper::class);
208+
$itemDocumentBuilder = app(Swis\JsonApi\Client\ItemDocumentBuilder::class);
209+
$blogRepository = app(App\Repositiories\BlogRepository::class);
210+
211+
$itemDocument = $itemDocumentBuilder->build(
212+
$typeMapper->getMapping('blog'),
213+
request()->all(['title', 'author', 'date', 'content', 'tags']),
214+
request()->id
215+
);
216+
$blogRepository->save($itemDocument);
217+
```
218+
219+
### Relations
220+
221+
The `ItemHydrator` also hydrates (nested) relations.
222+
A relation must explicitly be listed on the item in the `$availableRelations` array in order to be hydrated.
223+
If we take the above example, we can use the following attributes array to hydrate a new blog item:
224+
225+
``` php
226+
$attributes = [
227+
'title' => 'Introduction to the JSON API',
228+
'author' => [
229+
'id' => 'f1a775ef-9407-40ba-93ff-7bd737888dc6',
230+
'name' => 'Björn Brala',
231+
'homepage' => 'https://github.com/bbrala',
232+
],
233+
'date' => '2018-12-02 15:26:32',
234+
'content' => 'JSON API was originally drafted in May 2013 by Yehuda Katz...',
235+
'tags' => [
236+
1,
237+
15,
238+
56,
239+
],
240+
];
241+
$itemDocument = $itemDocumentBuilder->build($typeMapper->getMapping('blog'), $attributes);
242+
243+
echo json_encode($itemDocument, JSON_PRETTY_PRINT);
244+
245+
{
246+
"data": {
247+
"type": "blog",
248+
"attributes": {
249+
"title": "Introduction to the JSON API",
250+
"date": "2018-12-02 15:26:32",
251+
"content": "JSON API was originally drafted in May 2013 by Yehuda Katz..."
252+
},
253+
"relationships": {
254+
"author": {
255+
"data": {
256+
"type": "author",
257+
"id": "f1a775ef-9407-40ba-93ff-7bd737888dc6"
258+
}
259+
},
260+
"tags": {
261+
"data": [{
262+
"type": "tag",
263+
"id": "1"
264+
}, {
265+
"type": "tag",
266+
"id": "15"
267+
}, {
268+
"type": "tag",
269+
"id": "56"
270+
}]
271+
}
272+
}
273+
},
274+
"included": [{
275+
"type": "author",
276+
"id": "f1a775ef-9407-40ba-93ff-7bd737888dc6",
277+
"attributes": {
278+
"name": "Björn Brala",
279+
"homepage": "https://github.com/bbrala"
280+
}
281+
}]
282+
}
283+
```
284+
285+
As you can see in this example, relations can be hydrated by id, or by an associative array with an id and more attributes.
286+
If the item is hydrated using an associative array, it will be included in the resulting json unless `setOmitIncluded(true)` is called on the relation.
287+
288+
N.B. Morph relations require a 'type' attribute to be present in the data in order to know which type of item should be created.
289+
290+
291+
## Clients
292+
293+
This package offers two clients; `DocumentClient` and `Client`.
294+
295+
### DocumentClient
296+
297+
This is the client that you would generally use e.g. the repository uses this client internally.
298+
Per the [JSON API spec](http://jsonapi.org/format/#document-structure), all requests and responses are documents.
299+
Therefore, this client always expects a `\Swis\JsonApi\Client\Interfaces\DocumentInterface` as input when posting data and always returns this same interface.
300+
This can be a plain `Document` when there is no data, an `ItemDocument` for an item, a `CollectionDocument` for a collection or an `InvalidResponseDocument` when the server responds with a non 2xx response.
301+
302+
The `DocumentClient` follows the following steps internally:
303+
1. Send the request using your HTTP client;
304+
2. Use [art4/json-api-client](https://github.com/art4/json-api-client) to parse and validate the response;
305+
3. Create the correct document instance;
306+
4. Hydrate every item by using the item model registered with the `TypeMapper` or a `\Swis\JsonApi\Client\Item` as fallback;
307+
5. Hydrate all relationships;
308+
6. Add meta data to the document such as [errors](http://jsonapi.org/format/#errors), [links](http://jsonapi.org/format/#document-links) and [meta](http://jsonapi.org/format/#document-meta).
309+
310+
### Client
311+
312+
This client is a more low level client and can be used, for example, for posting binary data such as images.
313+
It can take everything your request factory takes as input data and returns the 'raw' `\Psr\Http\Message\ResponseInterface` wrapped in a `\Swis\JsonApi\Client\Response`.
314+
It does not parse or validate the response or hydrate items!
315+
316+
204317
## Service Provider
205318

206319
The `\Swis\JsonApi\Client\Providers\ServiceProvider` registers the `TypeMapper`, `JsonApi\Parser` and both clients; `Client` and `DocumentClient`.
@@ -278,6 +391,7 @@ If you discover any security related issues, please email [email protected] inste
278391

279392
The MIT License (MIT). Please see [License File](LICENSE) for more information.
280393

394+
281395
## SWIS
282396

283397
[SWIS](https://www.swis.nl) is a web agency from Leiden, the Netherlands. We love working with open source software.

0 commit comments

Comments
 (0)