Skip to content

Commit e6c3012

Browse files
committed
Merge pull request #16 from ninjapenguin/validation-exception
Adds validation error handling
2 parents be65f1c + f9ea099 commit e6c3012

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php namespace EchoIt\JsonApi\Exception;
2+
3+
use EchoIt\JsonApi\Exception;
4+
use EchoIt\JsonApi\MultiErrorResponse;
5+
use Illuminate\Support\MessageBag as ValidationMessages;
6+
7+
/**
8+
* Validation represents an Exception that can be thrown in the event of a validation failure where a JSON response may be expected.
9+
*
10+
* @author Matt <[email protected]>
11+
*/
12+
class Validation extends Exception
13+
{
14+
protected $httpStatusCode;
15+
protected $validationMessages;
16+
17+
/**
18+
* Constructor.
19+
*
20+
* @param string $message The Exception message to throw
21+
* @param int $code The Exception code
22+
* @param int $httpStatusCode HTTP status code which can be used for broken request
23+
* @param Illuminate\Support\MessageBag $messages Validation errors
24+
*/
25+
public function __construct($message = '', $code = 0, $httpStatusCode = 500, ValidationMessages $messages = NULL)
26+
{
27+
parent::__construct($message, $code);
28+
29+
$this->httpStatusCode = $httpStatusCode;
30+
$this->validationMessages = $messages;
31+
}
32+
33+
/**
34+
* This method returns a HTTP response representation of the Exception
35+
*
36+
* @return JsonApi\MultiErrorResponse
37+
*/
38+
public function response()
39+
{
40+
return new MultiErrorResponse($this->httpStatusCode, $this->code, $this->message, $this->validationMessages);
41+
}
42+
}

src/EchoIt/JsonApi/Handler.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,33 @@ protected function handleGetDefault(Request $request, $model)
526526
return $results;
527527
}
528528

529+
/**
530+
* Validates passed data against a model
531+
* Validation performed safely and only if model provides rules
532+
*
533+
* @param EchoIt\JsonApi\Model $model model to validate against
534+
* @param Array $values passed array of values
535+
*
536+
* @throws Exception\Validation Exception thrown when validation fails
537+
*
538+
* @return Bool true if validation successful
539+
*/
540+
protected function validateModelData(Model $model, Array $values)
541+
{
542+
$validationResponse = $model->validateArray($values);
543+
544+
if ($validationResponse === true) {
545+
return true;
546+
}
547+
548+
throw new Exception\Validation(
549+
'Bad Request',
550+
static::ERROR_SCOPE | static::ERROR_HTTP_METHOD_NOT_ALLOWED,
551+
BaseResponse::HTTP_BAD_REQUEST,
552+
$validationResponse
553+
);
554+
}
555+
529556
/**
530557
* Default handling of POST request.
531558
* Must be called explicitly in handlePost function.
@@ -537,6 +564,8 @@ protected function handleGetDefault(Request $request, $model)
537564
public function handlePostDefault(Request $request, $model)
538565
{
539566
$values = $this->parseRequestContent($request->content, $model->getResourceType());
567+
$this->validateModelData($model, $values);
568+
540569
$model->fill($values);
541570

542571
if (!$model->save()) {

src/EchoIt/JsonApi/Model.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php namespace EchoIt\JsonApi;
22

3+
use Validator;
34
use Illuminate\Database\Eloquent\Collection;
45
use Illuminate\Database\Eloquent\Model as BaseModel;
56
use Illuminate\Database\Eloquent\Relations\Pivot as Pivot;
@@ -121,6 +122,37 @@ public function getResourceType()
121122
return ($this->resourceType ?: $this->getTable());
122123
}
123124

125+
/**
126+
* Validate passed values
127+
*
128+
* @param Array $values user passed values (request data)
129+
*
130+
* @return bool|Illuminate\Support\MessageBag True on pass, MessageBag of errors on fail
131+
*/
132+
public function validateArray(Array $values)
133+
{
134+
if (count($this->getValidationRules())) {
135+
$validator = Validator::make($values, $this->getValidationRules());
136+
137+
if ($validator->fails()) {
138+
return $validator->errors();
139+
}
140+
}
141+
142+
return True;
143+
}
144+
145+
/**
146+
* Return model validation rules
147+
* Models should overload this to provide their validation rules
148+
*
149+
* @return Array validation rules
150+
*/
151+
public function getValidationRules()
152+
{
153+
return [];
154+
}
155+
124156
/**
125157
* Convert the model instance to an array. This method overrides that of
126158
* Eloquent to prevent relations to be serialize into output array.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php namespace EchoIt\JsonApi;
2+
3+
use Illuminate\Http\JsonResponse;
4+
use Illuminate\Support\MessageBag as ValidationMessages;
5+
6+
/**
7+
* MultiErrorResponse represents a HTTP error response containing multiple errors with a JSON API compliant payload.
8+
*
9+
* @author Matt <[email protected]>
10+
*/
11+
class MultiErrorResponse extends JsonResponse
12+
{
13+
/**
14+
* Constructor.
15+
*
16+
* @param int $httpStatusCode HTTP status code
17+
* @param mixed $errorCode Internal error code
18+
* @param string $errorTitle Error description
19+
* @param Illuminate\Support\MessageBag $errors Validation errors
20+
*/
21+
public function __construct($httpStatusCode, $errorCode, $errorTitle, ValidationMessages $errors = NULL)
22+
{
23+
$data = [ 'errors' => [] ];
24+
25+
if ($errors) {
26+
foreach ($errors->keys() as $field) {
27+
28+
foreach ($errors->get($field) as $message) {
29+
30+
$data['errors'][] = [ 'status' => $httpStatusCode, 'code' => $errorCode, 'title' => 'Validation Fail', 'detail' => $message, 'meta' => ['field' => $field] ];
31+
32+
}
33+
34+
}
35+
}
36+
37+
parent::__construct($data, $httpStatusCode);
38+
}
39+
}

0 commit comments

Comments
 (0)