Skip to content

Commit 6bb3d70

Browse files
committed
Update README.
1 parent 12c2888 commit 6bb3d70

File tree

2 files changed

+88
-3
lines changed

2 files changed

+88
-3
lines changed

README.md

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,85 @@ JSON should be *semantically* correct. E.g. when a client is providing a resourc
99
`attributes` member must be an object.
1010

1111
This package provides framework agnostic validation of the received request body content - so that it can be handled
12-
knowing that not only has `json_decode` successfully run, but that the structure of the decoded JSON is as expected.
13-
Provided decoders also returns decoded content as `StandardObject` instances, an object that provides a number of
12+
knowing that not only has `json_decode` successfully run, but that the structure of the decoded JSON is as expected.
13+
Provided decoders also returns decoded content as `StandardObject` instances, an object that provides a number of
1414
helper methods for handling the decoded content e.g. within a controller.
1515

16+
## Let's see an example...
17+
18+
A common scenario would be to decode received input for a resource object and then attempt to access its supplied
19+
attributes within a controller. For example:
20+
21+
``` php
22+
class ArticleController
23+
{
24+
25+
public function createAction()
26+
{
27+
$content = ... // get HTTP request body content.
28+
$data = json_decode($content, true);
29+
$attributes = $data['data']['attributes'];
30+
}
31+
}
32+
```
33+
34+
This is unsafe because the controller is assuming that the decoded `$data` is an array, has a `data` key, which
35+
itself is an array with an `attributes` key. This cannot be assumed because a client request cannot be trusted.
36+
37+
Also, the JSON-API spec specifies certain errors that must be sent if the provided input for a create resource under
38+
certain scenarios - e.g.:
39+
40+
> A server MUST return `409 Conflict` when processing a `POST` request in which the resource object's `type` is not among
41+
the type(s) that constitute the collection represented by the endpoint.
42+
43+
However, the controller has not checked whether `$data['type']` exists or whether it is an expected type.
44+
45+
The above example can be refactored to use validators to parse the provided content before handling it within the
46+
controller:
47+
48+
``` php
49+
50+
use CloudCreativity\JsonApi\Validator\Resource\ResourceObjectValidator;
51+
use CloudCreativity\JsonApi\Validator\Document\DocumentValidator;
52+
use CloudCreativity\JsonApi\Decoders\DocumentDecoder;
53+
54+
class ArticleController
55+
{
56+
57+
public function getArticleValidator()
58+
{
59+
$validator = new ResourceObjectValidator();
60+
61+
$validator->type('article')
62+
->attr('title', 'string')
63+
->attr('content', 'string')
64+
->belongsTo('author', 'person')
65+
->required(['author']);
66+
67+
return $validator;
68+
}
69+
70+
public function getDecoder()
71+
{
72+
$validator = new DocumentValidator($this->getArticleValidator());
73+
return new DocumentDecoder($validator);
74+
}
75+
76+
public function createAction()
77+
{
78+
$content = ... // get HTTP request body content.
79+
/** @var CloudCreativity\JsonApi\Object\Document\Document $data */
80+
$data = $this->getDecoder()->decode($content);
81+
$attributes = $data->getResourceObject()->getAttributes();
82+
}
83+
}
84+
85+
```
86+
87+
In this refactored controller, `$data` can be used knowing that it has passed validation of the JSON API spec, and has
88+
been cast to an instance of `CloudCreativity\JsonApi\Object\Document\Document`, providing a fluid interface for
89+
handling the input within the controller.
90+
1691
## Status
1792

1893
This repository is under active development and is currently in a pre-release state.

src/Validator/Document/DocumentValidator.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ class DocumentValidator extends AbstractValidator
5858
*/
5959
protected $_dataValidator;
6060

61+
/**
62+
* @param ValidatorInterface|null $dataValidator
63+
*/
64+
public function __construct(ValidatorInterface $dataValidator = null)
65+
{
66+
if ($dataValidator) {
67+
$this->setDataValidator($dataValidator);
68+
}
69+
}
70+
6171
/**
6272
* @param ValidatorInterface $validator
6373
* @return $this
@@ -130,4 +140,4 @@ protected function validateData($data)
130140

131141
return $this;
132142
}
133-
}
143+
}

0 commit comments

Comments
 (0)